Dynamic link to ng-model - angularjs

I have a table which is created by a jQuery component. In each row there is a select component which I can set to be linked to a ng-model, something like this:
<select ng-model="categories" ng-options="k as v for (k,v) in categories"></select>
My problem is that I don;t know when it is rendered, so I had to use n ugly $timeout, but even calling $scope.$apply() it doesn't bind to the items.
How can I force binding the select with element.
P.S. I'm using AngularJS 1.6

If you have some js code (i.e. jQuery) that creates some angular html, you need to $compile all created html so bindings will work.
I.e. this:
angular.element(document.body).append(angular.element('<input ng-model="x"/>'));
will just add some html, while this:
angular.element(document.body).append($compile(angular.element('<input ng-model="x"/>'))($scope));
will add input and bind x to its value.
http://plnkr.co/edit/PyIO02p3EHzpmC0cUA4V?p=preview

Related

Special character display along with their name in md-select

I have md-select with the values from the database. The value having a name with special characters. I am using angularjs material.
Example: In database: Sathya & ram,
It displays like: Sathya &amp ram in md-option.
How can I resolve this?
You could wrap the value into a div with the directive ng-bind-html like this:
<div ng-bind-html="$ctrl.name"></div>
This directive evaluated Html, so use with care
Docs for ngBindHtml
EDIT
I think you could also assign the directive to md-option directly.

Represent ng-model in a controller

I am developing application using AngularJS and ASP.Net MVC...
In my view, I have used ng-repeat=u in users in a div. Inside it, I set the ng-model in a textbox as ng-model=u.fName where fName is database field.
My question is, how I can represent the ng-model=u.fName in the angular controller??
For example, I tried to use $scope.n.fName but it doesn't work.
Note that u is only existing in ng-repeat block.
If you want to show/access to value changed by textbox outside of block, you should access via users again with another ng-repeat block:
<li ng-repeat="u in users">{{u.fName}}</li>
Or add ng-change="change(u)" to your textbox to get u anytime it's changed.
<input ng-model="u.fName" ng-change="change(u)" />
Plunkr example

Can i use ng-model with <p> tag?

I am new to angular-js and i think this is a basic question how to get the value from a paragraph tag in angular-js? I tried with using ng-model but doesn't giving the value.Can anyone help me?
ng-model is working for two way binding. p tag is not supported for ng-model. if you want to bind p tag then you can use ng-bind or {{}}.
<p ng-bind="test"></p>
plunker code here with ng-bind
No. You can not use ng-model for <p> tag. If you want to show the value of scope variable inside <p> tag, Then you can use expressions.
Example
<p> {{ variable }} </p>
This will show the value of variable into paragraph.
Ng-model is not supported for P,H tags,,,
if you want to bind tags then use ng-class
<p ng-class="localUser.yourdata">{{localUser.yourdata}}</p>
<h1 ng-class="localUser.yourdata">{{localUser.yourdata}}</h1>
hope this is help full
You can only directly mutate that ng-model in the controller to which the view is binded via an input tag. You could use {{}} or ng-bind for one way binding, from controller to view. But to achieve two way data binding you need an input tag or other alternatives like select.
In your case if you want to read changes inside other tags like p tags you need to watch those tags inside the scope, using $scope.$watch and listen for updates have a callback function execute on change.
So basically you can't achieve what your trying to do here. This is because p tags have static values and they do not change, so one way data binding is the best option here, from controller to view during the initialization of that tag. No point, later, would you be able to change the value inside the p tag, thus no need for two data binding here. Thus ng-model is not supported. Only ng-bind or {{}}.

Can I generate a dropdwon list without garbage code and bindings?

I want to generate a drop down list, which I will use on different places by cloning the html. Is it possible to generate the dropdown code without the bindings and garbage code like ng-option etc?
If I generate the dropdown list using the code like
<select ng-model="userGroups" ng-options="grp.groupId as grp.groupName for grp in groups" class="form-control">
</select>
and then clone this select using jquery, will the bindings will be copied too?
You can use ng-include to reuse template code. In that case you need to ensure that there is a groups object in your current scope which hold all the options for the select.
You could also wrap it in a directive to dynamically assign a model to the select. That could look like this:
<my-select ng-model="userGroups" my-options="groups" />
As Bixi already said: do not mix angular with jquery when it comes to DOM manipulation. It will cause you problems on all fronts.

Cannot get textarea value in angularjs

Here is my plnkr: http://plnkr.co/edit/n8cRXwIpHJw3jUpL8PX5?p=preview You have to click on a li element and the form will appear. Enter a random string and hit 'add notice'. Instead of the textarea text you will get undefined.
Markup:
<ul>
<li ng-repeat="ticket in tickets" ng-click="select(ticket)">
{{ ticket.text }}
</li>
</ul>
<div ui-if="selectedTicket != null">
<form ng-submit="createNotice(selectedTicket)">
<textarea ng-model="noticeText"></textarea>
<button type="submit">add notice</button>
</form>
</div>
JS part:
$scope.createNotice = function(ticket){
alert($scope.noticeText);
}
returns 'undefined'. I noticed that this does not work when using ui-if of angular-ui. Any ideas why this does not work? How to fix it?
Your problem lies in the ui-if part. Angular-ui creates a new scope for anything within that directive so in order to access the parent scope, you must do something like this:
<textarea ng-model="$parent.noticeText"></textarea>
Instead of
<textarea ng-model="noticeText"></textarea>
This issue happened to me while not using the ng-if directive on elements surrounding the textarea element. While the solution of Mathew is correct, the reason seems to be another. Searching for that issue points to this post, so I decided to share this.
If you look at the AngularJS documentation here https://docs.angularjs.org/api/ng/directive/textarea , you can see that Angular adds its own directive called <textarea> that "overrides" the default HTML textarea element. This is the new scope that causes the whole mess.
If you have a variable like
$scope.myText = 'Dummy text';
in your controller and bind that to the textarea element like this
<textarea ng-model="myText"></textarea>
AngularJS will look for that variable in the scope of the directive. It is not there and thus he walks down to $parent. The variable is present there and the text is inserted into the textarea. When changing the text in the textarea, Angular does NOT change the parent's variable. Instead it creates a new variable in the directive's scope and thus the original variable is not updated. If you bind the textarea to the parent's variable, as suggested by Mathew, Angular will always bind to the correct variable and the issue is gone.
<textarea ng-model="$parent.myText"></textarea>
Hope this will clear things up for other people coming to this question and and think "WTF, I am not using ng-if or any other directive in my case!" like I did when I first landed here ;)
Update: Use controller-as syntax
Wanted to add this long before but didn't find time to do it. This is the modern style of building controllers and should be used instead of the $parent stuff above. Read on to find out how and why.
Since AngularJS 1.2 there is the ability to reference the controller object directly instead of using the $scope object. This may be achieved by using this syntax in HTML markup:
<div ng-controller="MyController as myc"> [...] </div>
Popular routing modules (i.e. UI Router) provide similar properties for their states. For UI Router you use the following in your state definition:
[...]
controller: "MyController",
controllerAs: "myc",
[...]
This helps us to circumvent the problem with nested or incorrectly addressed scopes. The above example would be constructed this way. First the JavaScript part. Straight forward, you simple do not use the $scope reference to set your text, just use this to attach the property directly to the controller object.
angular.module('myApp').controller('MyController', function () {
this.myText = 'Dummy text';
});
The markup for the textarea with controller-as syntax would look like this:
<textarea ng-model="myc.myText"></textarea>
This is the most efficient way to do things like this today, because it solves the problem with nested scopes making us count how many layers deep we are at a certain point. Using multiple nested directives inside elements with an ng-controller directive could have lead to something like this when using the old way of referencing scopes. And no one really wants to do that all day!
<textarea ng-model="$parent.$parent.$parent.$parent.myText"></textarea>
Bind the textarea to a scope variable's property rather than directly to a scope variable:
controller:
$scope.notice = {text: ""}
template:
<textarea ng-model="notice.text"></textarea>
It is, indeed, ui-if that creates the problem. Angular if directives destroy and recreate portions of the dom tree based on the expression. This is was creates the new scope and not the textarea directive as marandus suggested.
Here's a post on the differences between ngIf and ngShow that describes this well—what is the difference between ng-if and ng-show/ng-hide.

Resources