AngularJs Passing complex data to directive

I have the following directive:

<div teamspeak details="{{data.details}}"></div>

this is the object structure:

data: {
details: {
serverName: { type: 'text', value: 'my server name' },
port: { type: 'number', value: 'my port' },
nickname: { type: 'text' },
password: { type: 'password' },
channel: { type: 'text' },
channelPassword: { type: 'password' },
autoBookmarkAdd: { type: 'checkbox' }
}
}

and I want it to generate a link based on the data inside the data.details object. Unfortunately it doesn't work since somehow I cann't access any inner values of the details object, but if I am passing it a simple data structure like:

<div teamspeak details="{{data.details.serverName.value}}"></div>

I can access it by using {{details}}.

Here is my Directive Code:

App.directive('teamspeak', function () {
return {
restrict: 'A',
template: "<a href='ts3server://{{details.serverName.value}}:{{details.port.value}}'>Teamspeak Server</a>",
scope: {
details: '@details',
},
link: function (scope, element, attrs) {
}
};
});

Thanks

82537 次浏览

Read on Angularjs official site explanation :

@ or @attr - bind a local scope property to the value of DOM attribute. The result is always a string since DOM attributes are strings. If no attr name is specified then the attribute name is assumed to be the same as the local name. Given and widget definition of scope: { localName:'@myAttr' }, then widget scope property localName will reflect the interpolated value of hello \{\{name}}. As the name attribute changes so will the localName property on the widget scope. The name is read from the parent scope (not component scope).

So you can send only a string, to pass an object, you need to set-up a bi-directionnal binding using =.

   scope: {
details: '=',
},

And your HTML will looks like

<div teamspeak details="data.details"></div>

Someone asked about how to do it without isolating scope, here is a solution:

<div teamspeak details="\{\{data.details}}"></div>

App.directive('teamspeak', function () {
return {
restrict: 'A',
template: "<a href='ts3server://\{\{details.serverName.value}}:\{\{details.port.value}}'>Teamspeak Server</a>",
link: function (scope, element, attrs) {
if(attrs.details){
scope.details = scope.$eval(attrs.details);
}
}
};
});

We can even use $interpolate if any values in attrs.details should be dynamically set with angular \{\{...}} expressions...

scope.details = scope.$eval($interpolate(attrs.details)(scope));

(don't forget to inject $interpolate service into your directive)

Important Note: I have not tested this method with angular 2.