Angularjs - ng-model undefined - javascript

I am building a rather complex directive in which I need access to ng-model on a specific element in the template which is enclosed into ng-if directive... I have a plunker and the explanation on how to see the issue is below.
In the .compile function of the directive I have a line of code that looks like this
ngModel = elm.find('textarea').controller('ngModel');
console.log(ngModel);
In my template, I have a something like this:
<div ng-if="views.view">
<textarea ng-model="exp.val"></textarea>
</div>
When I use ng-show my console.log gets an object of ng-model, no problem ...
The requirement is very strict however and I have to use ng-if. When I use ng-if my console log gets undefined
The actual working version of the problem exists in this plunker
If you change the line 6 in template.html into ng-if you can see the behavior.
How do I have to write this line to retrieve the model when inclosed in ng-if.
ngModel = elm.find('textarea').controller('ngModel');
I also tried using attach-if directive by Simon Sparks. This directive is pretty cool, it preserves the scope unlike ng-if so if you specifically need to not render HTML but you need to preserve scope it works great.
I still have the same problem with invoking ngModel as I am doing it but because of applying custom filters in the directive I have to update ng-model in this way.
I am this one step away from finishing this directive. Hoping someone can help.

Related

can element using ng-repeat access variable created by ng-repeat?

is this valid for ng-repeat in angularjs 1.7.x
<div
ng-repeat="item in items"
ng-class="item.id">
{{tab.label}}
</div>
I am confused with the usage of variable created by ng-repeat ie item in the element which it is attached to. I thought we can use it inside that element only.
I have checked that this works but wanted to understand if there is any example in documentation for this case.
As an extension to this , does ng-controller works the same way for keys attached to $scope.
Kindly give some reference as i have checked for ng-repeat that it works, i just want to understand why( or that it is the expected behavior)

AngularJS Directive - Multiple directives same name

Let's say I have multiple directives with the same name "parent-elem" (on each page I can have a different number of these directives - dynamic number)
<div ng-app="app">
<div parent-elem></div>
<div parent-elem></div>
<div parent-elem></div>
</div>
Is there a way to know (inside the link function) AngularJS finished render all the directives with the same name on the page?
Inside the directive link function - how do I know this directive is the last rendered?
Note: Not using a ng-repeat
You should have had written, same directive, multiple times :P
Now, that totally depends on your directive, how you make it.
It can keep the counter in a service or rootScope may be whenever it is initialized.
If you are using ng-repeat which you should in this case, you have a bool $last that can tell you if the element rendered is last or not, which you can pass to the directive via any attribute.

Angular conditionally use directive attr inside directive template

I have a problem with using directive conditionally inside another directive,
so let's say I have one directive 'myGrid' and in it's template I have something like this:
<table my-grid-resizable>...</table>
and I want to use myGridResizable directive only if I use myGrid directive like this:
<my-grid resizable="true" />
But I don't want to use ng-if inside template of myGrid directive.
I tried this:
if (scope.resizable) {
angular.element(element).find('table').attr('my-grid-resizable', ''); }
But it's not working, attribute is added but directive is not working, recompiling directive is't helping as well.
Thanks for help in solving this
You're just setting the attribute, however, this does not mean that the DOM will be digested on it's own. The reason your DOM doesn't update is because you're not updating any model or binding. You're just modifying the DOM.
So you're gonna have to manually compile your element like,
First, inject $compile in your directive or controller (whichever is applicable)
Then do:
if (scope.resizable) {
angular.element(element).find('table').attr('draco-grid-dynamic-table', '');
var html = angular.element(element).find('table').html();
var compiledHtml = $compile(html)(scope);
angular.element(element).find('table').html(compiledHtml);
}
This way, however works, but is not an angular way and is highly discouraged.
I do not understand why you don't want to use ng-if structure. It is the angular way of doing things.

Where and how to modify transcluded content?

I want to buid a directive (let's call it "A") that accepts HTML for transcluded content and modify its transcluded content by adding ng-click handlers on it using a custom logic.
I thought that the pre-link would be a good place to do this, but apparently I was very wrong (it seems that the docs suggest against it).
Every "A" directive will accept its own (unique) content, so I cannot do this in the compile phase.
In the link function I am not sure what I can do...
So, has anyone done anything similar?
EDIT:
I forgot to mention this: The handlers for ngClick should be defined on the directive's scope, not the parent scope. I don't know if Angular allows this, but that's what I need.
In your template you should add ng-transclude on the element want to add your custom html to.
your use of the directive:
<attribute ng-click="clickMe()">
<div>
transcluded data
</div>
</attribute >
and in your template:
<span ng-transclude>
</span>
Hope it makes sense :)

angular js input bind value

I have an input like this :
<input ng-model="mysearch.myfield" id="myid"/>
that is bound to a filter
<table><tr ng-repeat="row in list|filter:mysearch">...</tr></table>
If I modify the input value in the GUI, it works perfectly, but if I try to modify its value via javascript/jquery
$("#myid").val("newvalue")
The input value is updated but the mysearch.myfield is not modified
Actually, I have a list that appears on user actions (it does not exist on page load):
<li onclick="changeTheInputValue('newvalue1')">newvalue1</li>
<li onclick="changeTheInputValue('newvalue2')">newvalue2</li>
...
with
function changeTheInputValue(v) {
$("#myid").val(v);
}
And it does not work when I click on an "li" (the input value is updated, ut the mysearch.myfield is not modified)
I also tried
<li ng-click="mysearch.myfield = 'newvalue1'">newvalue1</li>
<li ng-click="mysearch.myfield = 'newvalue2'">newvalue2</li>
...
but it does not work :(
Any idea ?
Thanks,
any javascript executing outside the angulars event loop won't be efective in angular untill you apply it. in order to do that you need to get the relevant scope and $apply the changes, since is not clear, how and why you are modifying the value outside the angular scope there is nothing much i can say except you could do something like
function changeTheInputValue(v) {
$("#myid").val(v);
angular.element($("#myid")).scope().$apply();
}
that should let angular know about the changes, how ever this is a bad design if using angular. there are far better ways to accomplish this same thing w/o having mixed execution scopes. (angular/the rest);
You are modifying the value of the input "#myid" using direct DOM manipulation. AngularJS is not aware of this. If you want both the html and the value of mysearch.myfield to update correctly, you must do so by modifying the mysearch.myfield property directly, either in a controller or via an ng-model binding or something similar.
The main reason this isn't working for you has to do with how AngularJS modifies the DOM. When you use jQuery to modify the DOM, you are circumventing angular. Angular has no way of knowing if you have changed something in the DOM except if you do it directly through Angular itself. In particular, if you are curious, read about the $compile and $digest services.
Hope this helps shed some light on the subject!

Categories