How do I get data from an input to be reflected in the model if I use ng-model-options? - angularjs

I'm using the ng-model-options directive to ensure that I can complete the input of a value before the list reorders itself and the td containing the input hides.
The value is reflected in the view, however it isn't reflected in the model until I click on the sibling td that displays the char.initiative data.
The AngularJS documentation suggests that I invoke ngModel.NgModelController. It also suggests that the easiest way to reference the control's ngModel.NgModelController method is by making sure the input is placed inside of a form element that has a name attribute. The problem there is that I'm not using a form element.
How can I invoke ngModel.NgModelController to sync my view and model data up without using a form element? Is there any other way to sync my view and model that does not require the use of ngModel.NgModelController?
<tr ng-repeat="char in localChars | orderBy: '-initiative'">
<td>{{char.name}}</td>
<td ng-hide='char.show' ng-click='change(char)'>{{char.initiative}}</td>
<td ng-show='char.show'><input ng-blur='change(char)' ng-model='char.initiative' ng-model-options="{ updateOn: 'blur' }" type="text"></td>
</tr>

Related

Why ng-value and value attribute of input element hold different values

The input field value doesn't get the assigned ng-value.The dragItms object holds the value to be bound for the given col key.
When isSaveTemplt = true, collection and columns gets updated after api call.
The functionality that I implement is such that dragItems object changes on clicking tabs and the said api is called for getting the data for tbody element.
<th ng-if="isSaveTemplt && collection.length>0 && columns.length>0" ng-
repeat="col in columns track by $index">
<input class="filterStyle" type="search" placeholder="search
by {{col | translate}}" st-search="{{col}}" ng-value={{dragItms[col]}} />
</th>
I didn't get your question clearly, Maybe more code and explanation is needed. Unfortunately I dont have enough reputation to comment. But what I feel is the issue of using ng-if. Whenever ng-if is used it creates a child scope. So any element inside has a different scope. To access parent scope use $parent. So you access will be something like this {{$parent.dragItms[col]}}. $parent is parent scope.

Angular Js orderBy with input values

I'm having issues with the orderBy filter. The following code will order my initiative column just fine. When I type a value into the input, the filter automatically begins ordering the values just as I want it to.
However, if I type a value into the input that raises that character higher in the list the input will close out before I can finish typing that value.
If the value I type into the input drops the character lower down the list then that input does not close and allows me to finish typing my value.
Can anyone explain this behavior?
<tr ng-repeat="char in localChars | orderBy: '-initiative'">
<td>{{char.name}}</td>
<td ng-hide='show' ng-click='show = true'>{{char.initiative}}</td>
<td ng-show='show'>
<input ng-blur='initiative(char)' ng-model='char.initiative' type="text">
</td>
</tr>
Here is what I believe is the sequence of events:
User types in input changing the value of char.initiative.
This causes the list to reorder via the ng-repeat.
The scope of the ng-repeat is re-initialized causing the local show variable to lose its value (remember, ng-repeat has its own scope).
To fix this you'll need to use ng-model-options to control when the model value actually gets updated. You can choose to update on blur or use a debounce. Here is how to update on blur (my recommendation). You can find info on debouncing at the link.
<input ng-blur="initiative(char)"
ng-model="char.initiative"
ng-model-options="{ updateOn: 'blur' }"
type="text" />

How to make an xeditable select input mandatory (required) in AngularJS

I have an AngularJS project that uses Angular Bootstrap and I use the Angular-xeditable library for some edit-in-place fields in a table.
One of the inputs I have is a "select" input, i.e. a drop-down list that allows a user to select one option. (editable-select in xeditable).
I am trying to make this input mandatory when saving the form, but I cannot find a way to do this. Similar to all the x-editable controls I would expect that I can simply add an e- prefix to the standard angular directive to apply that directive to the xeditable control, that is, I should be able to add e-ng-required="true" to my control to make it mandatory. Yet this does not work. I do not get any errors when I add this, but it doesn't "do" anything. I can still save my form without selecting an item.
The following is a code sample of what I'm trying to do:
<form editable-form name="tableform" onaftersave="saveSubmissions()" oncancel="cancel()">
<table>
<!--Define table headings and columns...-->
<!--Define an ng-repeat to display each row-->
<tr ng-repeat="currentRow in dataRows">
<!--Add some columns for the row-->
<!--Add the select/drop-down column pertaining to this question-->
<td>
<span editable-select="currentRow.vendorID" e-ng-options="x.vendorId as x.name for x in vendors" e-form="tableform" e-ng-required="true">
{{showVendor(currentRow)}}
</span>
</td>
<!--Add some more columns for each row-->
</tr>
</table>
</form>
Even though I've set e-ng-required="true" on the element, it does nothing. How can I make the selection of an item mandatory using xeditable? I have searched for examples but couldn't find anything helpful.
Unfortunately required doesn't work with form validators as stated in the following links
Required field validation is not working
Validation field form using tag "form" with angular-xeditable
You have to manually check and set the validity of input onbeforesave and set validity of input element.
html
<span editable-select="currentRow.vendorID" e-ng-options="x.vendorId as x.name for x in vendors" e-form="tableform" e-name="vendor" onbeforesave="checkValidity()">
{{showVendor(currentRow)}}
</span>
js
$scope.checkValidity = function(){
if(valid){
$scope.tableform.$setValidity("vendor", true);
}
else{
$scope.tableform.$setValidity("vendor", false);
}
}

bind different value to ng-model on some condition

I have started using Angular and don't have much experience in it.
I am stuck with an issue. I am using ng-show and ng-model.
its like
<tr ng-show="responseValid">
<td> <input id="nameId" ng-model="model.name"/> </td>
</tr>
I am pre-populating the value in model.name.
Now if response is valid the input tag is shown otherwise not.
but when I submit the form, nameId value is bind by ng-model="model.name"
Issue here is I want model.name should not contain any value if response is not Valid i.e when input tag is hidden. but its not happening.
How can I nullify/empty the value in model.name? Is there anything available that I can use in the tag itself?
You should use ng-if instead of ng-show I believe.
ng-if removes elements from the DOM while ng-show only sets display:none.
When your send your model, check the state of the validResponse and set your model data based in this
example:
$scope.sendModel = function(){
$scope.model.name = $scope.validResponse? $scope.model.name : '';
}
A more advanced example http://codepen.io/gpincheiraa/pen/mPzmxO
You can use ngSwitch or ngIf.
<tr ng-if="responseValid">
<td> <input id="nameId" ng-model="model.name"/> </td>
</tr>
If the condition is not met, angular will completely remove the DOM element, till the condition will meet.

Angularjs ng-model nested inside ng-repeat updates all

This should be simple. For some reason, when using ng-model inside of ng-repeat it updates all ng-models inside that repeat loop.
Here's the code. Any ideas?
http://plnkr.co/edit/iAgrPwwBMilCyeReeLt9?p=info
Thanks.
Interesting!!!
Problem is that you are resetting row.field with an object from "$scope.columns"
in
<td>
<select ng-model="row.field" ng-options="column.title for column in columns"></select>
</td>
Here, row.field is reset with an object from $scope.columns and if you change this object in one row, as the other rows also use the same object, they repeat the same value.
You can change this model to row.field.type as
<td>
<select ng-model="row.field.type" ng-options="column.type as column.title for column in columns" ng-change="resetRow(row.field)"></select>
</td>
and define $scope.resetRow in your controller to reset other properties based on the field type.
Here is the updated plunker.
I would love to have a feature in ng-options to return a copy of
the object selected instead of the object reference to solve your problem though.

Resources