How to use ng-model as element rather than attribute? - angularjs

I want to use ng-model directive as element rather than as attribute inside tag,is there any way to do it?
well I've already designed my webpage in html and javascript and I want to include it in angularJS using "ng-include". So rather than adding attribute like,
<input type="checkbox" id="checkbox" name='rejectedPartsConfirmtodothis' ng-model="reject">
I want to put it in the format like, (as said in angulaJS documentation )
<ng-model>
<input --->
</ng-model>
but this is not working, any idea how can I make it work?

Quoting the content of the page
Usage
as element: (This directive can be used as custom element, but be aware of IE restrictions).
<ng-model>
...
</ng-model>

according to v1.5 official documentation : https://docs.angularjs.org/api/ng/directive/ngModel
Usage
as element: (This directive can be used as custom element, but be aware of IE restrictions).
<ng-model>
...
</ng-model>

I dont really think there would be a use case where you would really need to do this...instead try some alternative but use ng-model as an attribute as ng-model is a pre-defined directive given by angularjs...

You can build a new directive but you cannot modify ng-model to work as an element.

Related

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 {{}}.

When to use ng-attr?

It seems like using direct attributes and the ng-attr-* directive do the same thing. For example, the following render equivalently:
<div ng-attr-id="{{ 'object-' + value }}">ID</div>
<div id="{{ 'object-' + value }}">ID</div>
When should I use ng-attr-* and when should I use the direct HTML attribute?
ng-attr is used for add or not the attribute in context. If the expression {{undefined || null}}, the attribute is not added otherwise if has a value then attribute is added with the value {{ value }}.
The most common cases is in interpolation.
Related:
Conditionally adding data-attribute in Angular directive template
You use them for custom html data attributes - like if you wanted an attribute of let's say myData you would do
<div ng-attr-myData="{{ 'object-' + value }}">ID</div>
There are only a few situations where ng-attr-[attribute]="{{angular stuff}}" is different from just [attribute]="{{angular stuff}}". Certain elements within certain browsers can be broken if ng-attr is not used. Angular's documentation lists a few examples:
size in <select> elements (see issue 1619)
placeholder in <textarea> in Internet Explorer 10/11 (see issue 5025)
type in <button> in Internet Explorer 11 (see issue 14117)
value in <progress> in Internet Explorer = 11 (see issue 7218)
Source: https://docs.angularjs.org/guide/interpolation#-ngattr-for-binding-to-arbitrary-attributes
ng-attr can be used to dynamically assign value to an attribute of any html element.
One case, where I used it was to associate a label to a form control with dynamic id.
<label ng-attr-for="{{parameter.name}}">{{ parameter.name }}</label>
<input ng-attr-id="{{parameter.name}}" type="text">
Also, it can be used to assign dynamic value to a custom attribute.
Reference: here

Why doesn't 1-way binding work in angularjs?

I'm having trouble using one way binding in directives with an isolate scope.
If I use an equal sign for two-way binding, and use the data like so: {{d.name}}, it works.
If I use an # sign, it doesn't work. If I use an equal sign and use the data like so: {{::d.name}}, it fails also.
You can see my full example at this plunker: http://plnkr.co/edit/8bUl8pZSV8Ryru6GDq2M?p=preview
Can someone please help me understand what's happening here? Thanks.
The one-way binding syntax you are trying to use, has been introduced since Angular 1.3.
In your demo you are using version 1.2.25.
You must change the script link:
<script data-require="angular.js#1.3.x" src="https://code.angularjs.org/1.3.0/angular.js" data-semver="1.2.25"></script>
The problem with the second directive, instead, is that the # is not a one-way binding, it simply takes the attribute as text.
To use it like you would, so you need to interpolate the text before passing it to the directive, like this
<h3>Directive 2</h3>
<p ng-repeat="d in data">
<dir2 d="{{d.name}}"></dir2>
</p>
DEMO

Change value of input placeholder via model?

I'm trying to change the value of the input placeholder from a controller but cant quite figure out how.
input(type='text', ng-model='inputText', side='30', placeholder='enter username')
Is there a way to modify a model's element attributes?
You can bind with a variable in the controller:
<input type="text" ng-model="inputText" placeholder="{{somePlaceholder}}" />
In the controller:
$scope.somePlaceholder = 'abc';
The accepted answer still threw a Javascript error in IE for me (for Angular 1.2 at least). It is a bug but the workaround is to use ngAttr detailed on https://docs.angularjs.org/guide/interpolation
<input type="text" ng-model="inputText" ng-attr-placeholder="{{somePlaceholder}}" />
Issue: https://github.com/angular/angular.js/issues/5025
Since AngularJS does not have directive DOM manipulations as jQuery does, a proper way to modify attributes of one element will be using directive.
Through link function of a directive, you have access to both element and its attributes.
Wrapping you whole input inside one directive, you can still introduce ng-model's methods through controller property.
This method will help to decouple the logic of ngmodel with placeholder from controller.
If there is no logic between them, you can definitely go as Wagner Francisco said.
As Wagner Francisco said, (in JADE)
input(type="text", ng-model="someModel", placeholder="{{someScopeVariable}}")`
And in your controller :
$scope.someScopeVariable = 'somevalue'

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