2

I made a custom directive in angularjs with an isolated scope and passing argument. I try to check the argument in the controller/link of the directive because some times the argument is an array and i need only one item. but this don't work ( undefined object ).

- my directive :

directives.directive('dir.displaytaxoname', function () { return { restrict: 'E', replace: true, scope: { dfamily: '@' , dgenus: '@', dsn: '@' }, controller: function ($scope) { console.log($scope.dsn); // empty string in the console but ok in the rendered view /*function tools_isArray(arr) { return ( arr instanceof Array ); }*/ // if the dfamily argument is an array i just want the first item if(tools_isArray($scope.dfamily)){ $scope.dfamily = $scope.dfamily[0]; } if(tools_isArray($scope.dgenus)){ $scope.dgenus = $scope.dgenus[0]; } if(tools_isArray($scope.dsn)){ cl("indsn") ; $scope.dsn = $scope.dsn[0]; } }, templateUrl: "partials/elements/displaytaxoname.html" } }); 

- my templete :

<span> {{dfamily}}&nbsp;<i ng-show="dgenus!=''">{{dgenus}}&nbsp;</i><i>{{dsn}}</i><br> </span> 

- call to the directive :

<dir.displaytaxoname dfamily="{{specimen['T_FAMILY']}}" dgenus="{{specimen['T_GENUS']}}" dsn="{{specimen['T_SCIENTIFICNAME']}}"> </dir.displaytaxoname> 

I try many combinaison with link/controller but don't work. How can i do please ?

thanks

3 Answers 3

2

If you want to pass non-string values to your directive, you need to bind directly to outer-scope expressions, not to attribute values (see documentation), because attribute value is always a String.

Additionally, if you're not 100% sure the data will already by present on the outer scope when the directive is compiled, you need to $watch the data instead of just using the initial values.

scope: { dfamily: '=', // bind to expression instead of attribute value // ... }, controller: function ($scope) { // watch property value changes instead of using just the initial value $scope.$watch('dfamily', function (value) { if (tools_isArray(value)) { // be extremely careful not to create an infinite cycle here // (better save the modified values to different variables) $scope.dfamily = value[0]; } }); // ... } 

and

<tag dfamily="specimen['T_FAMILY']" ...></tag> 
Sign up to request clarification or add additional context in comments.

3 Comments

thank you for the answer. I still get undefined value in the controller if i log ( not in the html view ). sometimes the parameters are array and sometime a string.
i still get undefined maybe because the data i use in the directive call come from an asyncronus call to elasticsearch
thank you, with $watch it work. i post a complete answer merged with your's bellow
1

You have tested with = ?

scope: { dfamily: '=' , dgenus: '=', dsn: '=' } 

1 Comment

thank you for the answer. I still get undefined value in controller.
0

[complete working solution based on @hon2a answer]

this is a directive with isolated scope who take an array in parameter. it use $watch because the array parameter is provided after an asynchronus call in the main controller

- main controller :

// in a asynchronus call to elasticsearch elasticsearch.search({ index: $index, size:1, body: { "query": $query } }).then(function (response) { $scope.specimen = response.hits.hits[0]["_source"]; $scope.taxonamedata = { "T_FAMILY" : $scope.specimen["T_FAMILY"] , "T_GENUS": $scope.specimen["T_GENUS"], "T_SCIENTIFICNAME": $scope.specimen["T_SCIENTIFICNAME"], //scientific name "D_IDENTIFIEDBY": $scope.specimen["D_IDENTIFIEDBY"], "D_CREATED":$scope.specimen["D_CREATED"] } ; } .... 

- call to the directive :

<dir.displaytaxoname data="taxonamedata"></dir.displaytaxoname> 

- the directive :

 directives.directive('dir.displaytaxoname', function ($filter) { return { restrict: 'E', replace: true, scope: { data: '=' }, controller: function ($scope) { // watch property value changes instead of using just the initial value $scope.display = ""; $scope.$watch('data', function (value) { if(tools_defined(value)){ var tmp = value; // copy it to tmp variable to avoid loop when change for (var v in tmp) { if (tools_isArray(tmp[v])) { // convert all the array to string tmp[v] = tmp[v][0]; } } $scope.display = tmp["T_FAMILY"] + '&nbsp;'; if (tools_defined(tmp["T_GENUS"])) { $scope.display += '<i>' + tmp["T_GENUS"] + '</i>&nbsp;'; } if (tools_defined(tmp["T_SCIENTIFICNAME"])) { $scope.display += '<i>' + tmp["T_SCIENTIFICNAME"] + '</i><br>'; } $scope.display += tmp["D_IDENTIFIEDBY"] ; if (tools_defined(tmp["D_CREATED"])) { $scope.display += '&nbsp;('+$filter('date')(tmp["D_CREATED"], "dd/MM/yyyy")+')'; } } }); }, plain:true, template: '<span ng-bind-html="display | unsafe"></span>' } }); 

- the unsafe filter who display hmtl :

interfaceApp.filter('unsafe', function ($sce) { return function (val) { return $sce.trustAsHtml(val); }; }); 

function tools_isArray(arr) { return ( arr instanceof Array ); } function tools_defined(object){ return (( typeof object != undefined) && ( typeof object != "undefined") && ( object != null ) ) ; } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.