How to get a variable attribute of an HTML element? - javascript

I have a ng-repeat in which I have set an attribute like so:
<div ng-repeat="item in itemsList"
stepType="{{item.stepType}}">
{{item.itemValue}}
</div>
item.stepType can have values 'task' or 'action'
I'm trying to get the attribute 'stepType' like so:
let stepType = el.getAttributeNode("stepType");
console.log(stepType.value);
The result i'm getting is:
{{item.stepType}}
But the expected result is task or action
I also tried to get the attribute using the function getAttribute() but the result is the same.
I also noticed that in the above code if i log the value of stepType instead of stepType.value, i get the object which looks like this stepType: 'task'
How can i get the expected value?

If the attribute name is normalized:
<div ng-repeat="item in itemsList"
step-type="{{item.stepType}}">
{{item.itemValue}}
</div>
A custom AngularJS directive can $observe the attribute:
app.directive("stepType", function() {
return {
link: postLink
};
function postLink(scope, elem, attrs) {
attrs.$observe("stepType", function(value) {
console.log(value);
});
}
})
The console will log changes to the interpolated value of the attribute.

Try removing the double quotes. Replace this
<div ng-repeat="item in itemsList"
stepType="{{item.stepType}}">
{{item.itemValue}}
</div>
with
<div ng-repeat="item in itemsList"
stepType={{item.stepType}}>
{{item.itemValue}}
</div>

Related

Cannot interpolate vm.value in template - AngularJS

I am updating and modifying a project using Angular JS 1.2.25.
I have my controller where I have a value called vm.stageValue which is then called in template with an ng-if, so when the vm.stageValue increments it shows different containers. But whhen I define a value on the vm object that I want to interpolate on the template, eg a string that will be used and will not change on the template, I cannot seem to get it display.
This has makes me think I have not set up my controller correctly using the vm method.
It seems weird that I can use the ng-if and call function from the controller using ng-click on the template but I cannot interpolate a string or send it to another child component
Code is below, thank you in advance. Any help would be hugely appreciated
Controller
angular
.module('formModule')
.controller('NewBusinessFormCtrl', [
function() {
let vm = this;
// Methods used in controller
vm.methods = {
incrementStageValue: incrementStageValue,
decrementStageValue: decrementStageValue,
canIncrement: canIncrement,
canDecrement: canDecrement
};
//Initial stage values
vm.stageValue = 1;
vm.maxStageValue = 7;
// This is the string that I want to interpolate below
vm.contactFormCategory = 'New Business';
}
]);
Template of Controller
<div class="new_busines_cf" ng-controller="NewBusinessFormCtrl as vm">
<div class="form_wrapper">
<div ng-if="vm.stageValue == 1">
<input-text
class="form_input"
ng-model="ngModel"
input-text-label="This is the label">
</input-text>
// I want to send the vm.contactFormCategory into the component
// Value is sending but the component display 'vm.contactFormCategory'
// Not the value set in the controller
<form-headline
form-headline-sup-title="vm.contactFormCategory"
form-headline-text="This is a form headline text">
</form-headline>
</div>
// Trying to interpolate value here into template, but nothing display
{{vm.contactFormCategory}}
<div ng-if="vm.stageValue == 2">
<input-text
class="form_input"
ng-model="ngModel"
input-text-label="This is the label of stage 2">
</input-text>
<form-headline
form-headline-sup-title="vm.contactFormCategory"
form-headline-text="This is a form headline text">
</form-headline>
</div>
<button ng-click="vm.methods.incrementStageValue()">Increment Value</button>
<button ng-click="vm.methods.decrementStageValue()">decrement Value</button>
</div>
</div>
** Form Headline **
angular
.module('formModule')
.directive('formHeadline', function() {
return {
restrict: 'E',
templateUrl: '/partials/form/form-headline.component.html',
scope: {
formHeadlineText: '#',
formHeadlineSupTitle: '#'
},
link: function () {
}
};
});
Change your ng-if to
<div ng-if="vm.stageValue === '2'">

Angular directives in $http response

Angular 1.5
My $http data service returns html encoded text with directives too, like ng-click in the text.
I need to display the html and have the ng-click directives get activated.
To display I am doing this and it works, but ng-clicks don't work:
<div class="mt10" ng-repeat="row in aqdas.Paragraphs" ng-cloak>
<span ng-bind-html="TrustDangerousSnippet(row.Text)" >
{{row.Text}}
</span>
</div>
Here is TrustDangerousSnippet:
$scope.TrustDangerousSnippet = function (text) {
var val = $sce.trustAsHtml(text);
return val;
};
How can I edit TrustDangerousSnippet so that the ng-click's in the text are turned on once $http downloads the code?
Use this Directive also with your code. to bind html element in directive use complie. it will work..
.directive('compile', ['$compile', function ($compile) {
return function(scope, element, attrs) {
scope.$watch(
function(scope) {
return scope.$eval(attrs.compile);
},
function(value) {
element.html(value);
$compile(element.contents())(scope);
}
);
};
}])
I added the Directive Suresh included and changed the HTML to look like this, it works now. (add 'compile' to the binding element)
<div class="mt10" ng-repeat="row in aqdas.Paragraphs" ng-cloak>
<span compile ng-bind-html="TrustDangerousSnippet(row.Text)" >
{{row.Text}}
</span>
</div>

How to apply directive conditionally in AngularJS?

I want to apply a simple directive conditionally using ngAttr. I don't understand why my directive is always displayed. So if I have an undefined / false variable I want to apply my directive: dirr.
When using ngAttr, the allOrNothing flag of $interpolate is used, so if any expression in the interpolated string results in undefined, the attribute is removed and not added to the element.
My code pen
<div ng-app="myApp" ng-controller="MainController" class="container-fluid">
<h2 ng-bind="currentVersion"></h2>
<hr>
<div ng-attr-dirr="hidden || undefined">Default div</div>
</div>
angular.module('myApp',[])
.directive('dirr', function(){
return {
restrict:'AE',
template:'<div>Div from directive</div>'
}
})
.controller('MainController',['$scope', function($scope){
$scope.currentVersion = 'Angular 1.3.6';
$scope.hidden = undefined;
}])
;
You can make use of AngularJS's inbuilt directive ng-if to check for the condition and execute it conditionally.
Example:
<div ng-if="{some_condition}">
<dirr></dirr> <!--Execute the directive on the basis of outcome of the if condition-->
</div>
Form documentation
All of the Angular-provided directives match attribute name, tag name, comments, or class name
so whenever angular matches a diretive with attribute name,it compiles the template and renders the html irrespective of attribute value.
anyway you can use scope in directive template.so use ng-hide with scope's hidden property
angular.module('myApp',[])
.directive('dirr',function(){
return{
restrict:'AE',
template:'<div ng-hide="hidden">Div from directive</div>',
}
})
.controller('MainController',['$scope', function($scope){
$scope.hidden=false;
}]);
The answers are true and the sample code you provided works for small issues, but when it comes resolving this problem on large applications you may want to take this approach:
Updated Pen
<div ng-app="myApp" ng-controller="MainController" class="container-fluid">
<h2 ng-bind="currentVersion"></h2>
<hr>
<div dirr value="{{hidden}}">Default div</div>
</div>
.directive('dirr', function($log){
var directiveInstance = {
restrict:'AE',
scope:{
value:'#'
},
link: function (scope, element, attrs, ctrl) {
if(attrs.value === 'true'){
console.log('directive on !!');
$log.debug('element',element);
element[0].innerHTML = '<div>hello ' + attrs.value + '</div>';
}
else {
console.log('directive off !!');
}
}
}
return directiveInstance;
})
This is more tidy and you may not want to duplicate your code using ngIf or ngSwitch directives in seperate divs when you have something like:
<table>
<thead dirr value="{{statement}}">
<tr>
<th>
CrazyStuffHere...
</th>
<th>
CrazyStuffHere...
</th>
....
</tr>
</thead>
</table>

Directive not triggering on change of attibute

I have a 2 dropdowns from which user makes selection. And based on those values, the attributes are sent to directives and corresponding function should get called.
The problem is that the directives are not called on the change of value.
Here is the html code:
<div ng-controller=visCtrl>
<select ng-model="selectedDistrict" ng-options="item as item for item in districts " ng-init="selectedDistrict='GUNTUR'"></select>
<select ng-model="selectedYear" ng-init="selectedYear='2005'" ng-options="item as item.YEAR for item in opendata | filter:{ DISTRICT: selectedDistrict }"></select>
<div ng-repeat="item in categories">
<div id="containervis-item" ng-init="init(item.value)" class="container col-sm-12">
<div scatter-chart city-name={{selectedDistrict}} crime-name={{item}} current-year={{selectedYear}} vis-file=dataFile id="divVisScatter-{{item}}" class="divVis divVisScatter col-sm-6">
{{item}}
</div>
<div linear-chart city-name={{selectedDistrict}} crime-name={{item}} vis-file=dataFile class="divVis divVisLine col-sm-6"></div>
</div>
</div>
</div>
Here is the directive code:
myApp.directive('scatterChart', function($window){
return{
restrict:'EA',
template:"<svg width='850' height='200'></svg>",
link: function(scope, elem, attrs){
var d3 = $window.d3;
var rawSvg=elem.find('svg');
var svg = d3.select(rawSvg[0]);
var cityName=attrs.cityName;
var crime=attrs.crimeName;
var year=attrs.currentYear;
console.log(cityName);//doesnt get called when selection is made
}
};
});
The the directive is called with initial values only. Also, upon making a selection, the DOM gets changed and the city-name and crime-name attributes get new value, but the function isnt called.
By 'the corresponding function should get called' you mean link function? Link function is executed once, after the compilation phase and it is the right place to attach event listeners to HTML template, etc. Check here for more details.
In case you want to execute a function everytime an attribute's value changes, you have to $watch it, and include all the necessary code into $watch function.
eg.
scope.$watch(function() {
return attrs.cityName;
}, function(value) {
console.log(value);
})

Issues with calling function from template

In one case I have a problem with running a function on the Controller from the template. The value becomes a string containing the function signature, not the value that should be returned from the function.
When I use {{ getSomeObject(d) }} in my template markup it works fine, and it prints the object values, meaning that the function got called on the Controller.
I have tried with and without the {{ }}.
Pseudo code:
<div class"xyz" data-lav-fact="getSomeObject(d)"> <!-- Does not work here -->
{{ getSomeObject(d) }} <!-- Works here -->
</div>
And of course the function is added to the scope in the Controller:
$scope.getSomeObject = function(data) {
return { key: "test" };
};
This works in other parts of the application and I don't know what wrong in this case.
Does anyone know what typically can be wrong here?
Since you are trying to set an attribute with a $scope function, you'll need to {{ interpolate }} and use ngAttr attribute bindings. Here is a simple example that shows this in action. Examine the difference between the elements logged out. As you dig, you'll see your { key: 'test' } value being set
<div id="without" data-lav-fact="getSomeObject()">without</div>
<div id="with" ng-attr-data-lav-fact="{{ getSomeObject() }}">with</div>
app.controller('ctrl', ['$scope', function($scope) {
$scope.getSomeObject = function() {
return { key: 'test' };
}
var w = angular.element(document.getElementById('with'));
var wo = angular.element(document.getElementById('without'));
console.log(w[0].attributes); // has value
console.log(wo[0].attributes); // does not have value
}]);
JSFiddle Link

Categories

Resources