AngularJs : Passing parameter to ng-click in directive - angularjs

I have a directive in which i am adding an a button and an ng-click on the button. My code for directive is
AppDirectives.directive(
'feed',
function() {
return {
restrict : 'AE',
scope : {
feedMsg : '#feedText',
feedUser : '#feedUser',
feedTimestamp : '#feedTimestamp',
feedLike : '#feedLike',
feedDislike : '#feedDislike',
likeClick: '&',
dislikeClick :'&',
feedUid : '#feedUid'
},
template : '<div class="media">'+
'<a class="pull-left" href="#"><img class="media-object" src="resources/images/holder.png" style="height:64px; width:64px;" alt="img"></a>'+
'<div class="media-body">'+
'<h4 class="media-heading">{{feedUser}}</h4>'+
'<h5>{{feedMsg}}</h5>'+
'<p> <a ng-click="likeClick(feedLike)">Like</a> {{feedLike}} <a ng-click="dislikeClick(feedUid)">Dislike</a> {{feedLike}} {{ feedTimestamp | date:medium }} </p>'+
'</div>'+
'</div>',
replace : true,
};
});
my html code is
<feed feed-uid={{feed.uid}} feed-text={{feed.feedText}} feed-user={{feed.userUid}} feed-timestamp={{feed.time}} feed-like={{feed.like}} like-click="likeClick(uid)" dislike-click="dislikeClick(uid)" feed-dislike={{feed.dislike}}></feed>
and my contoller have
$scope.dislikeClick = function(feedUid){
console.debug("dislike"+feedUid);
}
When i click on the dislike button, i get 'like undefined', where i am suppor to print the 'like uid_of_post'. can any one kindly tell me what is wrong with my code. As {{feedUid}} get the correct value inside the template.

from the documentation on $compile, which houses directive docs:
Often it's desirable to pass data from the isolated scope via an expression and to the parent scope, this can be done by passing a map of local variable names and values into the expression wrapper fn. For example, if the expression is increment(amount) then we can specify the amount value by calling the localFn as localFn({amount: 22}).
So in this case you'd be doing ng-click="dislikeClick({uid: feedUid})" and then from your html just do dislike-click="dislikeClick(uid)"
I'm answering to make this specific to your use case, but I think this is pretty much the same question as: AngularJS getting $event from a directive

Related

AngularJS directive passing dynamic ui-sref

I'm using the old AngularJS 1.5.11 in a large project and I'm trying to clean up my templates using directives.
I have an edit button directive in which I would like to pass through the ui-sref but when I do I get the error
Error: [$parse:syntax] Syntax Error: Token '}' not a primary expression at column 6 of the expression [{id: }] starting at [}].
Here is my directive
editButton = ->
return {
restrict: 'EA',
scope: {
sref: "#"
},
template: '
sref = {{sref}}
<button id="edit-btn"
class="mds__button -blue"
ui-sref={{sref}}>
<i class="fa fa-edit"></i> Edit
</button>
'
}
angular
.module('myApp')
.directive('editButton', editButton)
And here is how I call it
<edit-button sref="job_edit({id: {{job.id}}})" />
In my template I display the sref and it's correctly printed out but the button doesn't like the ui-sref.
Update
I got it working but it would be nice to refactor this so I pass the job_edit({id: job.id}) attribute and it works.
Directive;
editButton = ->
return {
restrict: 'EA',
scope: {
model: "#"
item: "="
},
template: '
<button id="edit-btn"
class="mds__button -blue"
ui-sref="{{model}}_edit({id: item.id})">
<i class="fa fa-edit"></i> Edit
</button>
'
}
angular
.module('myApp')
.directive('editButton', editButton)
Calling it in my templates;
<edit-button model="job" item="job" />
You can't make that sref = {{sref}} inside an Angularjs template.
When you declare sref on the scope object of the directive that means that your directive gets an isolated scope with sref property on it, with the value that was passed to the directive as an attribute.
This declaration has few possible values, such as, #, =, &.
# is used for an interpolation value, that means that whenever you pass a value to the attribute, you need pass some interpolation
<edit-button sref="{{somethingAvailableOnParentScope}}" />
= 2 way data binding, you need to pass some expression
<edit-button sref="somethingAvailableOnParentScope" />
& bind a function, used to pass a "pointer" to a function. (not relevant for our case)
To sum up, we want to pass the value of job_edit invokation to our directive, therefore we need to use =.
editButton = () => ({
restrict: 'EA',
scope: {
sref: "="
},
template: '
<button id="edit-btn"
class="mds__button -blue"
ui-sref="sref">
<i class="fa fa-edit"></i> Edit
</button>
'
});
angular
.module('myApp')
.directive('editButton', editButton)
And the usage will be something like that:
<edit-button sref="job_edit({id: job.id})" />

How to access the attribute of angular directive in templateUrl html content

How do I access the attribute of angular directive in templateUrl html content?
angular.module('myApp')
.directive('questionImage', function () {
return {
restrict : 'E',
scope : false,
templateUrl : 'templates/questionImage.html',
link : function(scope, element, attrs) {
scope.type = attrs['type'];
}
}
});
template HTML:
<div>
<label>Image Links</label><br>
<button type="button" ng-click="newImageLink('{{type}}')">+</button>
<span ng-repeat="imageLink in questionFormData.imageUrls['{{type}}'] track by $index">
<input type="text" ng-model="questionFormData.imageUrls['{{type}}'][$index]">
<button type="button" ng-click="removeElement(questionFormData.imageUrls['{{type}}'], $index)">-</button>
</span>
</div>
Inside this HTML, I need to access the "type" attribute value specified when the directive is used in DOM such as below.
<question-image type="optionAImages"></question-image>
<question-image type="optionBImages"></question-image>
How do I get "type" attribute value inside the template html?
Update: Added the 'link' function in the directive definition. I was able to get the type but its value is always the last directive usage.
i.e I always see optionBImages value for type attribute. optionAImages value is not available.
the problem comes from the scope:false statement as as the second call of the question-image directive override the parameter changed by the first call of the same parameter
you need to change the scope:false to be scope:true
this will not create an isolated scope but it will give the directive a nested scope of the parent scope of the controller.
return {
restrict : 'E',
scope : {
type : '#'
},
templateUrl : 'templates/questionImage.html'
This is equivalent to
scope.type = attrs.type;

Dynamically initialize a ng-model directive

I'm dynamically building a form with angular depending of the kind of input:
<div ng-controller="formController" ng-repeat="field in formFields" ng-switch="field.type">
<div ng-switch-when="text">
<!-- Something -->
</div>
<div ng-switch-when="dropdown">
<myDirective my-data="field.param" ng-model="field.model"></myDirective>
</div>
</div>
I've got two problems with my directive which builds a custom dropdown input:
Ng-model directive interprated the name field.model as plain text, whereas I would like the attributs ng-model="field.model" would be replaced by the value contained into field.model. Curly brackets don't seems to work here. Any idea?
How to let the ng-model value accessible both in my form controller, and into my custom directive's controller?
Exemple of a field object:
{
label : "Name",
model : "employeeName",
type : "dropdown",
param : {
dropdownArray : result,
dropdownName : 'Nom',
dropdownFieldValue : 'nameUUID',
dropdownVisibleValue : [ 'employeeSS', 'employeeName' ]
}
}
Then in my controller I should be able to access this dropdown value with: $scope.employeeName.
It sounds like you're accessing field.model via the attributes input parameter supplied to the link function in your directive. Instead, you should be accessing it via the scope variable.
link: function(scope, element, attributes) {
// attributes.ngModel will yield 'field.model'
// scope.ngModel will contain the actual value of field.model
}
If you don't explicitly define an isolate scope for your directive, then ng-model assigned to field.model should be available in your directive via the scope variable as I mentioned above.
scope: false // This is the default
// Define an isolate scope with field.model available through scope.ngModel
scope: {
ngModel: '='
}
Hope that helps.

Creating layout using Angular directives

Folks.. i am trying to layout a bunch of columns in tablular format using Angular directive but am lost after having written some code.
What's the issue?
I need to display a bunch of columns as shown in the plnkr (Display option 2). However I want to achieve this using directives.
Here is the plnkr:
http://plnkr.co/edit/yTDxfvkCJHwrEDZGQJeX
Any help will be appreciated
regards,
If you add a template to the directive, you can output the same markup as your first example:
demo.directive("customTable",function(){
return ({
restrict : "A",
template: '<span ng-repeat="element in header" ng-style="{width: element.width}" class="box">{{element.column}}</span>'
});
function link($scope, element, attributes){
console.log($scope.header);
console.log("now what");
}
});
This one uses the parent scope so you don't need the header attribute:
<h1>Display option 2: Use Directive </h1>
<div custom-table>
</div>
Here is an updated plunker.
You could also use Isolated Scope and two-way bind the header. This allows the header object to be bound between the parent scope and the directive scope:
demo.directive("customTable",function(){
return ({
restrict : "A",
scope: {
header = '='
},
template: '<span ng-repeat="element in header" ng-style="{width: element.width}" class="box">{{element.column}}</span>'
});
function link($scope, element, attributes){
console.log($scope.header);
console.log("now what");
}
});
And then you can declare header as you did originally:
<h1>Display option 2: Use Directive </h1>
<div custom-table header="header">
</div>

AngularJS - Evaluating options to a directive in the correct scope

Angular newbie here. Trying to wrap my head around directives, scopes, transclusions, and what not.
Here's what I'm trying to achieve -- each table in a cell needs to be color-coded (change in bgcolor OR addition of a specific CSS class) based on the value inside that cell. The complication is that the cell does not have a bare value - it has other bits & baubles along with it. Therefore, within the cell, I would like to have the ability to add custom HTML.
Here's what my template looks like:
<span color-codify="{'max' : object.max, 'value' : object.value}" ng-transclude>
{{ object.value }}
Edit | Delete
</span>
Here's what my directive looks like:
myModule.directive('colorCodify', function() {
return {
restrict: 'A',
transclude: 'true',
'link' : function(scope, element, attrs, controller) {
var opts = scope.$eval(attrs.colorCodify);
console.log(opts); // THIS DISPLAYs {max: undefined, value: undefined}
}
}
});
The surprising part is, that even though {{ object.value }} within the <span> element renders correctly, it is not being passed down to the directive properly. However, if I refer to $parent it works properly. Example:
<span color-codify="{'max' : $parent.object.max, 'value' : $parent.object.value}" ng-transclude></span>
What's going on?
<span color-codify="{'max' : object.max, 'value' : object.value}" ng-transclude>
{{ object.value }}
Edit | Delete
</span>
.
myModule.directive('colorCodify', function() {
return {
restrict: 'A',
transclude: 'true',
scope: {getOpts: "&colorCodify"},
'link' : function(scope, element, attrs, controller) {
var opts = scope.getOpts();
console.log(opts);
}
}
});
For more info, check out directive definition object part in http://docs.angularjs.org/guide/directive
Edit about $parent:
I suppose you need to read more about how scopes work in angular (how do they inherit from one another and how do they override those inherited properties). This would be one of the most important aspects in angularjs. I suggest you to follow the links and read them again and again until you get it.
ngScope Documentation Reference
Developer Guide
Bonus (video from angularjs team, discussing angularjs' best practises):
Youtube

Resources