Directive to format date in angularjs? - angularjs

I have a span in ng-repeat as follows:
span(humanize-date="{{file.date}}"
I'm to create a directive so that, directive changes the date format
directive('humanizeDate', [
function() {
return {
restrict: 'EA',
template: '<div value="{{formattedDate}}"/>',
replace: true,
scope: {
formattedDate: '=humanizeDate'
},
link: function(scope, elem, attrs) {
return scope.formatedDate = moment.duration(scope.humanizeDate).humanize();
}
};
}
]);

just use:
<span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>
here is more information about
https://docs.angularjs.org/api/ng/filter/date
hope to help

You should not use {{}} while you are using = inside your directive which indicated two way binding.
It should be direct variable reference rather than {{}}
span(humanize-date="file.date"
OR
Other way would be you could use # in your directive isolated scope as your are giving {{}} with expression to attribute which indicated one way binding.
scope: {
formattedDate: '#humanizeDate'
},

Related

First option selected by default in select tag when using templateURL with AngularJS

I am facing an issue I cannot quite understand with AngularJS.
I have a fairly simple select which behaves differently in two of my directives. In my first directive with templateURL, it selects the first option by default whereas it does not in my second one:
.directive("inputFieldSelectTpl", function() {
return {
restrict: 'E',
scope: {
ngModel: '=',
},
"templateUrl": "inputFieldSelect.tpl.html",
"link": function(scope, elem, attrs) {
scope.opta = attrs.opta;
scope.optb = attrs.optb;
}
};
});
.directive("inputFieldSelect", function() {
return {
restrict: 'E',
scope: {
ngModel: '=',
},
template: function(elem, attrs) {
var template =
'<select ng-model="ngModel">'+
'<option value='+attrs.opta+'>'+attrs.opta+'</option>'+
'<option value='+attrs.optb+'>'+attrs.optb+'</option>'+
'</select>';
return template;
}
};
});
with inputFieldSelect.tpl.html:
<select ng-model="ngModel">
<option value={{opta}}>{{opta}}</option>
<option value={{optb}}>{{optb}}</option>
</select>
I just cannot figure out why. I have read that I could add an empty option tag in templateURL to avoid this auto select but it adds an empty option which I would like to avoid for a mandatory form field. Is it normal or an angularJS bug?
(I do not mind about my model not having the select default value as I can force this later on.)
Here is a complete and simple Punker: http://plnkr.co/edit/tz5s6vjI83VyTKGycTzg
Thanks
If you attach a controller in the directive you can initialize the variable in the directive. I modified the Plunker:
http://plnkr.co/edit/bQwkV83jhPPsiqTs4nsK?p=preview
The change:
controller: function($scope) {
$scope.ngModel="Monetary"
}
Hopefully this works for what you are doing?
Actually I managed to make it work using a Prelink instead of a link:
http://plnkr.co/edit/zhcDBwJbzJ9Ilr0qfrLp?p=preview
"link": {
pre: function(scope, elem, attrs) {
scope.opta = attrs.opta;
scope.optb = attrs.optb;
}
}
I would say that this function has to be executed before the angularJS select directive otherwise its options are somewhat unknown, hence this undefined behaviour selecting the first value.

How do you pass in data to custom directives as a value of the attribute itself?

I have a directive defined as such:
angular.module("main.directives").directive("todo", function() {
return {
restrict: "A",
scope: {
todo: "=entity"
},
replace: false,
templateUrl: "todo.html",
link: function(scope, element, attributes) {
}
};
});
which I use like this from templates:
<div todo entity="todoData"></div>
todoData comes from a controller or some other the local scope. Anyway it all works like a charm, so that's cool!
My question is the following: How do I have to modify the directive definition so that it also works with a markup of this type:
<div todo="todoData"></div>
As you can see the data is now passed in as the value of the attribute marking the directive. Just like ng- directives do:
<p ng-repeat="bit in data"></p>
<p ng-click="whatever()"></p>
How can that be achieved?
Thanks
Replace
scope: {
todo: "=entity"
},
by
scope: {
todo: "=todo"
},
or simply
scope: {
todo: "="
},
When you write an attribute directive in angularjs you might want to have it fed by an attribute value.
For example, something like this:
<div my-attribute="somevalue"></div>
How then do you create a new scope that takes that in? It's not obvious. Any here's how you do it:
app.directive('myAttribute', function() {
return {
restrict: 'A',
scope: {
myAttribute: '='
},
template: '<div style="font-weight:bold">{{ myAttribute | number:2}}</div>'
};
});
The trick to notice is that the "self attribute" because of the name of the attribute in camel case.
Here is the Reference to This Answer!
you must eval the value of the attribute inself. The isolate scope is not one of my favorites kind of scopes for a directive. Instead you can use, scope = true, to inherit from the parent controller. This will allow you to use all the variable exposes on the parents scopes.
in your case.
angular.module("main.directives").directive("todo", function() {
return {
restrict: "A",
scope: true,
replace: false,
templateUrl: "todo.html",
link: function(scope, element, attributes) {
scope.todo = scope.$eval(attributes[todo]);
}
};
});
now your todo directive could be used. Like any other ng- directive.
example:
<div todo="getTodoList()"></div>
<div todo="[{description:'hahahha'}]"></div>

How to handle new attribute added to directive?

Here is my directive:
return {
restrict: 'E',
scope: {
showBorder: '='
},
link: function (scope, element) {
alert(scope.showBorder);
Here is my directive written inside HTML:
<my-directive showBorder="true"></my-directive>
But alert saying - scope.showBorder is undefined?
What did I miss here?
Atribute names are camelcase.
So if you define showBorder in the scope you need to reference it with show-borderin your directive html.
ex:
<my-directive show-border="true"></my-directive>

how to pass directive attribute to directive template?

I'm have this code:
<div ng-repeat="param in item.parameters">
<rating param_item="{{param}}"></rating>
</div>
how can i pass the given attribute to the directive template?
Personally, I like creating child scope for element directives:
http://plnkr.co/edit/Dz7fcZaT4KdRDa869rwm?p=preview
app.directive('rating', function() {
return {
restrict: 'E',
scope: {
paramItem: '#'
},
link: function(scope, element, attr){
console.log(scope.paramItem);
}
}
});
There are a couple other ways too, depending on how you expect your directive to work.

Accessing attributes from an AngularJS directive

My AngularJS template contains some custom HTML syntax like:
<su-label tooltip="{{field.su_documentation}}">{{field.su_name}}</su-label>
I created a directive to process it:
.directive('suLabel', function() {
return {
restrict: 'E',
replace: true,
transclude: true,
scope: {
title: '#tooltip'
},
template: '<label><a href="#" rel="tooltip" title="{{title}}" data-placement="right" ng-transclude></a></label>',
link: function(scope, element, attrs) {
if (attrs.tooltip) {
element.addClass('tooltip-title');
}
},
}
})
Everything works fine, at the exception of the attrs.tooltip expression, which always returns undefined, even though the tooltip attribute is visible from Google Chrome's JavaScript console when doing a console.log(attrs).
Any suggestion?
UPDATE: A solution was offered by Artem. It consisted in doing this:
link: function(scope, element, attrs) {
attrs.$observe('tooltip', function(value) {
if (value) {
element.addClass('tooltip-title');
}
});
}
AngularJS + stackoverflow = bliss
See section Attributes from documentation on directives.
observing interpolated attributes: Use $observe to observe the value changes of attributes that contain interpolation (e.g. src="{{bar}}"). Not only is this very efficient but it's also the only way to easily get the actual value because during the linking phase the interpolation hasn't been evaluated yet and so the value is at this time set to undefined.
Although using '#' is more appropriate than using '=' for your particular scenario, sometimes I use '=' so that I don't have to remember to use attrs.$observe():
<su-label tooltip="field.su_documentation">{{field.su_name}}</su-label>
Directive:
myApp.directive('suLabel', function() {
return {
restrict: 'E',
replace: true,
transclude: true,
scope: {
title: '=tooltip'
},
template: '<label><a href="#" rel="tooltip" title="{{title}}" data-placement="right" ng-transclude></a></label>',
link: function(scope, element, attrs) {
if (scope.title) {
element.addClass('tooltip-title');
}
},
}
});
Fiddle.
With '=' we get two-way databinding, so care must be taken to ensure scope.title is not accidentally modified in the directive. The advantage is that during the linking phase, the local scope property (scope.title) is defined.

Resources