AngularJS - Repeating a div and a button - javascript

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});

Related

Creating the multiple div dynamically using Javascript

I have div element and have a class for it. I want to create multiple div using that class, but I don't want to create nested div, I want to create div outside using Javascript. I used append property, but its create nested div below is html as I required. I need help.
//have this div
<div data-bind="dynamicDiv" class="one"></div>
//need to create multiple div
//Knockoutjs && javascript//
ko.bindingHandlers.dynamicDiv = {
init: function (element, valueAccessor) {
var parentclassName = element.className;
lastId += 1;
///it is creating nested div, want to create outside of parentclass not inside the parent class
$element.append(DivHtml(lastId,parentclassName));
},
};
function DivHtml(lastId,parentclassName) {
Newdiv = document.createElement('div');
Newdiv.id = "divId_"+lastId
document.querySelector("." + parentclassName).appendChild(Newdiv)
}
Fixes for your current code:
In DivHtml, the third line should be return NewDiv
init should append to element.parentElement using appendChild
You never define $element, it should be just element or $(element)
But even if you fix this, I don't understand what you're trying to achieve.
Your example doesn't really show why you'd need a custom binding handler for this. Seems to me that knockout's default bindings should suffice:
<div data-bind="attr: { id: 'divId_' + ++lastId }" class="one"></div>
If you need to copy the class name dynamically, I'd take care of that in a view model if I were you. Look in to the template and foreach bindings as well.
var className = "one";
var idPrefix = "divId_";
var nrOfElements = 5;
var elements = [];
for (var i = 0; i < nrOfElements; i += 1) {
elements.push({
className: className,
id: idPrefix + i
});
};
ko.applyBindings({items: elements });
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div data-bind="foreach: elements">
<div data-bind="attr: { id: id, 'class': className }, text: id"></div>
</div>

Get child element without id or class attributes with AngularJS

I have the following HTML code :
<div id="someId">
<div ng-transclude>
</div>
</div>
Really simple I am getting the div element which has ID attribute using the following function :
var getElementById = function (id) {
return angular.element("#" + id);
};
Where in this example case the ID is 'someId'. My goal is to get the div inside the one I just got. So I want to return the div with ng-transclude attribute. I believe that this will happen by getting an element by attribute name or something.
Thanks in advance.
PS: I can't put any other attributes in the div I wanted(like id) because in the real life it is far more complecated and the code is auto-generated.
I think this will help you
var getElementByAttribute = function (attribute) {
return angular.element(document).find('[' + attribute + ']');
};
var el = getElementByAttribute('ng-transclude')
I don't know if that will be the Angular way, but you can use native properties of the HTML element. Something like this:
var getElementById = function (id) {
return angular.element("#" + id);
};
var childDivWithTransclude = getElementById('someId').children[0];

How to change attribute of html in angular js?

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>

How to use a classname as a predefined variable?

How can I use a DOM classname to refer to a predefined variable, which has the same name as the className with JavaScript?
For example:
<div class="someContent"></div>
//JS
var someContent = "this is a JS variable";
div = document.querySelector(".someContent");
div.innerHTML = div.className;
This outputs:
<div class="someContent">someContent</div>
But I'm trying to output:
<div class="someContent">this is a JS variable</div>
Using the classname to link to my variable. Is there a way to use the classname to refer to the variable rather than the actual className?
No jQuery please.
Here is the fiddle i'm working on http://jsfiddle.net/f6WpJ/
You can use object and store values inside object:
var data = {someContent : "this is a JS variable"};
div = document.querySelector(".someContent");
div.innerHTML = data[div.className];
Fiddle
What you're trying to do is effectively abusing the semantics of element classes; to store data references you will be better off storing them as data attributes, e.g.:
<div class="someContent somethingElse" data-param="someContent"></div>
That way you decouple the data from any particular class list an element may have.
The code would then look like this:
var dataMap = {
someContent: "this is a JS variable"
};
div = document.querySelector(".someContent");
div.innerHTML = dataMap[div.getAttribute('data-param')];
If the browser supports dataset you can do:
div.innerHTML = dataMap[div.dataset.param];
Demo
you could do:
var someContent = "this is a JS variable";
div = document.querySelector(".someContent");
div.innerHTML = window[div.className];
demo:: jsFiddle
but there are better ways to do it as suggested by #dfsq
Note:: usage of window[div.className] assumes the variable is in global scope

Javascript get class text inside element

I have a bunch of span4 class elements in my html. they look something like this:
<div class="span4">
<div class="widget">
<div class="header">blablabla</div>
</div>
</div>
I want to sort the span4 by that text iside header class.
I do this to sort them
$(".span4").sort(sortAlpha)
but how do I select the text inside the header class?
I'm doing this but I guess there is a better way
function sortAlphaAsc(a,b){
var nomeA = $(a.childNodes[1].childNodes[1]).text();
var nomeB = $(b.childNodes[1].childNodes[1]).text();
return a.innerHTML.toLowerCase() > b.innerHTML.toLowerCase() ? 1 : -1;
};
there must be a better way than
$(a.childNodes[1].childNodes[1]).text()
var elems = $(".span4");
elems.sort(function(a, b) {
return $(a).find('.header').text().toUpperCase().localeCompare(
$(b).find('.header').text().toUpperCase()
);
});
$(".span4").parent().html(elems);​
FIDDLE
Try this:
function sortAlphaAsc(a,b){
var nomeA = $(a).find('div.header').text();
var nomeB = $(b).find('div.header').text();
return nomeA.toLowerCase() > nomeB.toLowerCase();
};
You could detach the spans, sort and append them.
That will be very fast too as changing elements in memory and only updating the DOM once in the end is very efficient.
var $spans = $(".span4").detach();
var sortedSpans = $spans.sort(function(spanA, spanB) {
var spanTextA = $("div.header", spanA).text();
var spanTextB = $("div.header", spanB).text();
return spanTextA > spanTextB;
});
$("body").append(sortedSpans);
Obviously instead of body you append it back to it's actual container element.
Or if the spans are in a common container store the parent in cache var $parent = $spans.parent() and in the end simply do $parent.html(sortedSpans).
I don't know your whole mark-up but that should get you started.
DEMO - Detach spans, sort them and append again
Do you mean something like this:
$('.span4').find('.header').text();
This will return the text inside the header div.

Categories