Angular Js orderBy with input values - angularjs

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" />

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.

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

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>

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.

Validating form using Angular when name field has dots and brackets

The form to be validated is master detail i.e. it has two portions. master portion contains two fields while detail portion initially has two rows but they can be increased by pressing a button on DOM. The form looks like the following
The problem is that in detail portion I have to create the inputs using ng-repeat like
<div class="form-group">
<table style="margin-left:10%;">
<tr>
<th>Account id</th>
<th>Amount</th>
</tr>
<tr class="edit-row" ng-repeat ="entry in model.Entries">
<td>
<input type="text" ng-model="model.Entries[$index].AccountId" required name="Entries[{{$index}}].AccountId"/>
</td>
<td>
<input type="text" ng-model="model.Entries[$index].Amount" required name="Entries[{{$index}}].Amount"/>
<span class="field-validation-error text-danger" ng-show="transactionForm['Entries['{{$index}}'].Amount'].$invalid && transactionForm['Entries['{{$index}}'].Amount'].$dirty">
Amount is Required
</span>
</td>
</tr>
</table>
</div>
But the ng-show attribute is not working fine for the detail portion. This is because, I have dots (.) and brackets ([) in the name of input fields. How can I perform validation in such scenario. Someone may argue to change the names of the input but I have to use this convention for input names in the detail portion. In current code, I have used bracket notation in ng-show attribute of Amount field as described in This SO question, but to no avail. you can find complete example at plunker
Can you do something like this?
ng-show="model.Entries[$index].Amount === ''"
Rather than trying to check the form value check the actual model value. This will work assuming you are just checking to make sure there is a value other than the empty string. You will have to make the check more specific to what you are looking for. You can also set the type="number" if you only want to allow the user to enter a numeric value.

AngularJS ng-repeat with ng-change

I'm trying to have a way to catch the change of a variable inside of an ngRepeat so that I can modify other properties. So I have this HTML:
<tr ng-repeat="variable in variables">
<td>
<div ng-if="....">
<textarea ng-model="variable.u_field_values" ng-change="onChange(variable)">
Whenever they modify the text in that textarea, I need to update another value on the current variable that's being used. The change method doesn't seem to ever get fired though.
Try putting the ng-change ahead of the ng-model:
<textarea ng-change="onChange(variable)" ng-model="variable.u_field_values">
I have found that order sometimes matters. No idea why, though..

Resources