I want to change attribute of a div in angularjs. I know how to do in jquery but not in angular.
html :
<div ng-app="test">
<div ng-controller="cont">
<button ng-click="updateStatus()">TOGGLE ATTRIBUTE </button>
<div id="test" {{status}}>TEXT </div>
</div>
</div>
js :
var angApp = angular.module('test',[]);
angApp.controller('cont', ['$scope', function($scope){
$scope.status = 'someattr';
$scope.updateStatus = function() {
if( $scope.status == 'someattr'){
$scope.status = '';
}else{
$scope.status = 'someattr';
}
};
}])
Here is jsfiddle to work with.
In jquery :
var div = $('#test');
$('button').on('click',function(){
if( div.attr('someattr'){
div.removeAttr('someattr');
}else{
div.attr('someattr',true);
}
})
I want to achive same in angularjs.
NOTE : I AM NOT TRYING TO ADD DISABLED STATE TO DIV. I JUST WANT TO TOGGLE AN ATTRIBUTE.
In your specific case (add disabled attribute), you have to use ng-disabled in order to bind its value to a $scope variable.
It makes no sense to use it on a div, I'll use a button instead to give you an example:
<button ng-click="updateStatus()">TOGGLE ATTRIBUTE </button>
<button id="test" ng-disabled='status'>TEXT</button>
see a working example HERE
UPDATE
To toggle an attribute, yo can use attr() and removeAttr():
el.attr("disabled", "true");
el.removeAttr("disabled");
See a complete example HERE
NOTE (thanks to jme11): as reported on Angular Dev Guide
Do not use controllers to:
Manipulate DOM — Controllers should contain only business logic. Putting any presentation logic into Controllers significantly affects its testability. Angular has databinding for most cases and directives to encapsulate manual DOM manipulation.
you should avoid to manipulate the DOM inside the controller.
Make a directive which uses .attr and .removeAttr in a $watch handler. Here's a modified version of your fiddle: http://jsfiddle.net/0eqz1qo1/1/
The directive:
.directive('addAttr', function() {
return function(scope, elem, attr) {
scope.$watch(attr.addAttr, function(val, prev) {
if(val)
elem.attr(val, "");
if(prev && prev !== val)
elem.removeAttr(prev);
});
}
})
Usage:
$scope.myVar = 'hello';
...
<div add-attr="myVar"></div>
becomes:
<div add-attr="myVar" hello></div>
You can not implement disable property for any div.But you can hide or show the div using Angular.js.Check the code below.
<div ng-app="test">
<div ng-controller="cont">
<button ng-click="updateStatus()">TOGGLE ATTRIBUTE </button>
<div id="test" ng-hide="hide-div" >TEXT </div>
</div>
</div>
JS:
var angApp = angular.module('test',[]);
angApp.controller('cont', ['$scope', function($scope){
$scope.hide-div = true;
$scope.updateStatus = function() {
if( $scope.hide-div == true){
//do something here
}else{
$scope.hide-div = true;
}
};
}])
Other option is you can also use ng-class in div and inside those class you can declare display:none,display:block
You can't add an attribute by this way with angularJS. If you inspect your code, you can see that the attribute that you're trying to pass in div is {{status}}(your expression), use existing attributes rather than create your own! For example: ng-disabled, ng-show, ng-hide.
It's not really right thing to do. I guess, cannot inject attribute with angularJS. {{status}} is an expression, it's like expression and will evaluate by angularjs while rendering to html. about expression: https://docs.angularjs.org/guide/expression
Replace your line :
<div id="test" {{status}}>TEXT </div>
with these :
<div id="test" someattr="" ng-if="status=='someattr'" >TEXT</div>
<div id="test" ng-if="status==''" >TEXT</div>
Related
I need help with some code with Angular. I'm pretty new to this (first post) so I'll try to explain the best I can. In short i want to add a class to a element ID when an email is an empty string. The contacts has an array of emails.
The main problem is that it seems that after the page renders the information the Element ID did not have the class added like i thought it would.
If i go into console on google chrome and do angular.element('id').addClass('class') it would works and does add the class to the element but when i put it on this function it does not show after the page renders.
Any help would be great! Thank you.
For example:
$scope.ContactResults.forEach(function (item, index) {
item.resourceID = index;
if (item.email == '') {
angular.element('#Contacts_email_externalLink-' + index).addClass('hide-icon');
}
});
You should use ng-class combined with $scope params for stuff like this. Don't manipulate the DOM with angular.element() directly:
View
<a href="mailto:who#ever.knows"
ng-class="{ 'hide-icon' : hideIcon }">Email external link</a>
Application logic:
$scope.hideIcon = false;
$scope.ContactResults.forEach(function (item, index) {
item.resourceID = index;
if (item.email.length === 0) {
$scope.hideIcon = true;
} else {
$scope.hideIcon = false;
}
});
What if instead of ids elements. use the ng-class
<form>
<div ng-repeat="item in ContactResults">
<input type="email" ng-model="item.email">
<div id="Contacts_email_externalLink-{{$index}}"
class="some-class"
ng-class="{true:'hide-icon', false:''}[item.email.length > 0]">
</div>
</form>
I have an html element as :
<i ng-click="run()"></i>
and in my controller:
$scope.run() = function($event) {
var el = $event.currentTarget;
}
now how can i want to add some classes on the el element but el.addClass('class-name') is not working
I can only use javascript here not jquery
ng-class="expression"
Its recommended that you use ng-class instead of using controller to add class.
but you can use element.classList.add('className') also if you want
When modifying classes on elements using the classList API you need to use the classList namespace. i.e.
el.classList.add('class-name');
It looks like you are still thinking in jQuery.
html:
<i ng-click="run($event)"></i>
JS:
$scope.run() = function(event) {
var element = angular.element(event.currentTarget);
element.addClass('new');
}
You can use ng-class here is the demo Jsfiddle demo
Js code
var app = angular.module('app', []);
app.controller('ctrl', function($scope) {
$scope.myClass = false;
$scope.addClass = function() {
$scope.myClass = true;
}
});
HTML
<div ng-app="app">
<div ng-controller='ctrl'>
<span ng-class='{myClass:myClass}'>This my content</span>
<button ng-click='addClass()'>
Add class
</button>
</div>
</div>
I think a more propriate way to do it, is to use ng-class for your i element, and bind it to some variable on your scope.
Example:
Your HTML:
<i ng-click="changeClass()" ng-class="myClass"></i>
Your Angular controller:
function Controller($scope){
$scope.myClass = "";
$scope.changeClass = function() {
$scope.myClass = //Put here your CSS class
}
}
You can use ng-class in Angular js
<i ng-class="myclass" ng-click="run()"></i>
in controller
$scope.run() = function(event) {
$scope.myclass="classname";
}
Simply add like this,in HTML
<i ng-click="run($event)">i</i>
In contoller
$scope.run = function($event) {
$event.target.classList.add("className")
}
I want to use ng-repeat to repeat a div. This div also has a button within it.
Currently, I'm doing it by creating the div and the button in the javascript part and pushing the final result in an array :
var newDiv = document.createElement('div');
var newButton = document.createElement('button');
newDiv.appendChild(newButton);
$scope.arrayDiv.push(newDiv);
I have 2 questions :
1) What should be the html syntax ? Is the following correct ?
<div id='main_chart_div' ng-repeat="x in arrayDiv" value={{x}}></div>
2) Is there a way to do that without manipulating the DOM ?
You can have the button in your template:
<div id='main_chart_div' ng-repeat="x in arrayDiv" value={{x}}>
<button></button>
</div>
By the way, you shouldn't repeat an element with a static id.
One possible way is to use ng-bind-html within ng-repeat.
ng-bind-html evaluates the expression and inserts the resulting HTML into the element in a secure way.
Secure way is with either ngSanitize or make use of $sce. Demo
Filter directive for safe binding:
app.filter('safeHtml', function ($sce) {
return function (val) {
return $sce.trustAsHtml(val);
};
});
View :
<div id='main_chart_div' ng-repeat="x in arrayDiv">
<p ng-bind-html="x.html | safeHtml"></p>
</div>
Controller:
$scope.arrayDiv = [{html: '<h1>Heading</h1>'}];
var newDiv = document.createElement('div');
var newButton = document.createElement('button');
newButton.innerHTML = "Button";
newDiv.appendChild(newButton);
$scope.arrayDiv.push({html : newDiv.outerHTML});
I need to subscribe to an existing binding of a DOM element. As an example, I have the following input element:
<div id="MyDiv">
<input id="MyInput" data-bind="enable: isEnabled()" />
</div>
Now, assuming I only have access to the DOM element, I need to do something like this:
var inputElement = $("#MyInput");
var bindings = ko.utils.getBindings(inputElement); // getBindings does not exist
var enableBinding = bindings["enable"];
if (enableBinding != undefined) {
enableBinding.subscribe(function (value) {
if (value == false)
$("#MyDiv").addClass("disabled");
else
$("#MyDiv").removeClass("disabled");
})
}
Is there a way to do this?
Update: I've extended the sample so that you see my use case for this: The div here is automatically generated by a preprocessor and needs the disabled class on it when the input is disabled. It does not work if the attribute is only changed on the input element. The addition/removal must be transparent...
Short answer: Don't do this. There is a reason that getBindings is not a particularly visible function in the Knockout toolkit.
Long answer: You can, through a bit of indirection, get at the original binding.
HTML:
<div id="MyDiv">
<input id="MyInput" data-bind="enable: isEnabled" />
</div>
<input type="checkbox" data-bind="checked: isEnabled" />
JS:
var viewModel = function() {
self.isEnabled = ko.observable(true);
}
ko.applyBindings(new viewModel());
var input = $('#MyInput')[0];
function getBinding(element, name) {
var bindings = ko.bindingProvider.instance.getBindings(input, ko.contextFor(input));
return bindings.hasOwnProperty(name) ? bindings[name] : null;
}
var binding = getBinding(input, 'enable');
binding.subscribe(function(value) {
if (value == false)
$("#MyDiv").addClass("disabled");
else
$("#MyDiv").removeClass("disabled");
});
Working JSFiddle
EDIT: Found a shorter way
Again, if there is any way you can convince your preprocessor to add a CSS observable, do so. Mucking about with bindings in this manner relies on the particular quirks of Knockout 3.3.0's internal implementation, which can change in future releases.
Checkout the answer provided here.
In short, you can use
var viewModel = ko.dataFor(domElement);
to get the viewmodel that is bound to that DOM element. You can then, subscribe to any observables attached to that viewmodel.
I am trying to pass a value from a html element angularJS method bound to the $scope.
The code is...
<div ng-app ng-controller="miniC">
<input name="someitem" ng-blur="CalculateTotals(this)"/>
</div>
function miniC($scope){
$scope.myAccounts = new Array();
$scope.CalculateTotals = function(amt){
console.log(amt);
}
}
codepane link
But I cannot seem to extract the value from the element. I do not want to bind in this case as I am trying some things out and this was one of the approaches I had....
Angular expressions are all properties of the scope they are evaluated on, so this will just be the current scope.
With this in mind, you have to make this available on the scope. The simplest way is to use ng-model="someValue", then use ng-blur="CalculateTotals(someValue)".
However I also note in your question you explicitly don't want to bind, and this does add some overheads if you don't use anything else, so you would have to create a custom directive instead.
Append ng-model="testVal" to your input field and console.log($scope.testVal); to log your value.
The easiest way is to turn an input into a model's representation with ng-model directive, allowing to access its value directly. But if, for some reasons, you don't want to do this, you still can access this element - via target property of $event variable exposed by ngBlur directive. For example:
HTML:
<div ng-app ng-controller="miniC">
<input name="someitem" ng-blur="AddToTotal($event.target)" />
<button type="button" ng-click="Reset()">Reset</button>
<br />
<span>Totals: {{ CalculateTotals() }}</span>
</div>
JS:
function miniC($scope) {
$scope.myAccounts = [];
$scope.Reset = function() {
this.myAccounts.length = 0;
}
$scope.CalculateTotals = function() {
return this.myAccounts.reduce(function(sum, el) {
return sum + el;
}, 0);
};
$scope.AddToTotal = function(inp) {
var value = inp.value;
this.myAccounts.push(+value);
};
}
Demo. It works somewhat funny, as a new value is added each time focus is moved out of that input.