Angularjs - Inserting directives dynamically to dom element - javascript

I'm trying to set a directive to my inputs accordingly.
So let's say I have this input:
<input type="foo" id="myinput" maskvalue> </input>
This works fine on my app, the problem is when I try to insert "maskvalue" dynamically using the "setAttribute" it doesn't work, here's what I'm trying to do right now:
element = document.getElementById('myinput');
if(element){
element.setAttribute('maskvalue', "");
}
This code will successfully insert my directive to the dom element, but will take no effect. It seems that is impossible to insert a custom directive to the dom when it was already loaded, am I wrong?
But that's basically the question, how can I insert a directive dynamically to a dom element?
Thanks

Use Angular's $compile command to Angular-ize this. Basically, you need to notify Angular that you have made a change so it can do its magic.
function MyController($scope, $compile) {
element = document.getElementById('myinput');
if (element) {
element.setAttribute('maskvalue', "");
$compile(element)($scope);
}
}
Make sure you do this in an Angular controller that has $compile and $scope injected into it.

Related

ng-click not working when using append function

I am trying to call a function using ng-click when dynamical elements are created but with no success so far. Here is my code
$scope.myfunc = function(){
alert("anything")
}
var divtoappend=angular.element( document.querySelector('#slist'));
divtoappend.append("<button class = 'optv' ng-click='myfunc()'>" +mybutton+ "</button>");
...
No error is thrown and nothing happens on click
You have to compile DOM with $compile API, before injecting into DOM tree, like below.
divtoappend.append($compile("<button class = 'optv' ng-click='myfunc()'>" +mybutton+ "</button>")($scope));
By compiling DOM angular will put all HTML level bindings in $$watchers array of $scope to make sure UI is up to date on every digest cycle.
You need to compile the dynamically generated HTML so that it is under the scope of AngularJS.
Just compile inside append method like
divtoappend.append($compile("<button class = 'optv' ng-click='myfunc()'>" +mybutton+ "</button>")($scope));
Before this inject $compile in your controller.
I have created a plunkr see this plunkr link
You need to compile your DOM elements as follow using $compile
$compile(divtoappent)(scope);

Angular dynamically add ng-click to many elements

I have an Ionic application with an SVG object with many rectangles (e.g. <rect class="info" id="1001" width="20" height="20" transform="translate(40,40)" />). I would like to add an ng-click directive to each of these without going through and manually appending ng-click to each of them.
Currently, instead, I have the following code in the controller:
$(document).ready(function() {
$('#svg').on('click', 'rect.info', dispInfo);
}
This works as needed, but does not seem to be the "Angular" way. Is there a better way of doing this?
I have tried the following which seemed more angular, yet to no avail:
var elems = $('#svg rect.info');
elems.attr('ng-click', 'dispInfo()');
$compile(elems);
This successfully adds the ng-click directive to the proper elements, but they do not fire. Could it be a problem with the way I am calling $compile ?
To be in more angular way, why cant to wrap your svg rectangle with a directive and add ng-click as part of directive template?
The problem I see with your code is, $compile function accepts html template.
You can try the below,
var elems = $('#svg rect.info'),
$parent = elems.parent();
elems.attr('ng-click', 'dispInfo()');
elems = $compile(elems.html())($scope); // pass your scope variable instead of $scope
$parent.empty().append(elems);

Angular Js - Manipulate DOM and add click behaviour

I am using a leaflet map with angular and added a legend. To change the appearance of the map I manipulated the DOM after the view has loaded with a $timeout-method. The legend should be clickable to select which items should appear on the map. So I tried to make an alert, when one item in the legend is clicked. For that I changed the item to a button just to be sure. But the button click doesn't work because it doesn't know the method.
Does anybody know how to call a ng-click method on a manipulated DOM object?
Here is some of my code:
controller.js
//initiating of the map happend before
//now loading of the markers and manipulating of the map
function activate() {
projectService.getMarkers(vm, 'projectsData');
bindEventListener();
$timeout( function() {
getLegendElement();
});
}
//manipulating of the legend element to make a button with a ng-click
function getLegendElement() {
var element = document.getElementsByClassName("legend leaflet-control");
element[0].children[0].innerHTML = '<button ng-click="showAlert()">ok</button>';
}
//showing the alert
$scope.showAlert = function(){
$window.alert("foo");
}
Your DOM manipulation SHOULD be moved to a directive. However, if you wanted to keep it in your controller, you need to inject $compile into your controller and invoke it on your dynamically generated html.
function getLegendElement() {
var element = document.getElementsByClassName("legend leaflet-control");
element[0].children[0].innerHTML = '<button ng-click="showAlert()">ok</button>';
$compile(element)($scope);
}
The reason for this is because Angular looks for event bindings that it needs to generate when it first parses your template. Since you are applying a late event that needs binding to html that did not exist when your template was originally parsed, you need to tell Angular to update its understanding of the template. The documentation calls this out:
$compile
Compiles an HTML string or DOM into a template and produces a template function, which can then be used to link scope and
the template together.

Finding a specific element tag in angularJS

I'm working with angularJS and would like to remove/modify the class of a specific child element (who's class/id is unknown because it is being added to the parent element dynamically).
I understand that using angular you can say something like:
angular.element('someknownParentClass').addClass('newClass');
However, I want to do something similar to:
angular.element('.someknownParentClass').find('i').addClass('newClass');
The class 'someknownParentClass' is a class assigned to an 'a' tag, and inside this tag, I have an 'i' tag with a glyphicon icon class that I would like to change from inside a specific function. It seems like this method isn't working. I know angular's jqLite has a children() attribute, but i'm a little unsure of how to use this or if it would be useful in this case, or maybe using jQuery with angular would be my best option (from what I understand, that's different than jqLite). Any suggestions?
I'm assuming you're doing this in a directive, in which case you can do something like:
var elem = angular.element('.someknownParentClass');
var iElems = elem.children('i');
iElems.addClass("newClass");
If you're more comfortable in jQuery, I don't see a problem in using it in an angular directive instead. According to the docs, angular.element is an alias for jQuery:
https://docs.angularjs.org/api/ng/function/angular.element
$('.someknownParentClass').find('i').addClass("newClass");
You shouldn't need to use angular.element if you are doing things within a directive. If you want to use angular.element in code, you are probably better off using jQuery. I put together a sample jsfiddle that binds a directive to a pre-defined class (some-known-parent-class) and searches for all the "i" elements under it and adds newClass class to it:
var mod = angular.module("myApp", []);
mod.directive("someKnownParentClass", function () {
return {
restrict: "C",
link: function (scope, element, attrs) {
element.find("i").addClass("newClass");
}
}
});
This way, you are decoupling the direct DOM manipulation (i.e. angular.element) through using a directive to do the manipulation. Fiddle here.

Dynamically adding directive to element in Angular

I have a directive called "resizable" that adds functionality to an element to make it resizable.
I want to conditionally apply this directive to an element from a controller.
When I add this directive at run-time using attr, the attribute for the "resizable" directive is added, but the directive doesn't execute.
Here's an illustration: http://jsfiddle.net/HB7LU/3995/
What I'm expecting is that when $('span').attr('resizable', ''); is called, the class funky should be added to the span. Why doesn't it?
You need to use the $compile directive to notify angular of the changes. Basically the logic goes like this: "I've changed something within my element that you should be concerned about. Please compile the DOM against my scope":
function Controller($scope, $compile) {
// Apply resizable directive to span
var span = $('span');
span.attr('resizable', '');
$compile(span)($scope);
}
Documentation here
NOTE: You SHOULD NOT use jQuery natively within a controller (... or anywhere really). It may select span tags outside of your element of interest. You SHOULD try writing a directive to wrap the logic that applies your resizable directive.

Categories

Resources