I have a set of divs, inside a ng-repeat. When I use a ng-model for these, they are all updating when I change the value of this model from a function in the controller. i.e., If I change the model, all the divs are reflecting the same value.
Html:
<tbody ng-repeat="aw in aws">
<div ng-model="currentValue" ng-init="initializeSelects(aw.id)">{{currentValue}}</div>
Controller code:
$scope.initializeSelects = function(awId)
{
$scope.currentValue = "read";
}
I tried changing my code to:
<tbody ng-repeat="(i, aw) in aws track by $index">
<div ng-model="currentValue[i]" ng-init="initializeSelects(aw.id, i)">{{currentValue[i]}}</div>
and
$scope.initializeSelects = function(awId, i)
{
$scope.currentValue[i] = "read";
}
In this case, currentValue always is undefined and the model value can not be changed. Why would it be undefined?
Any inputs would be helpful, thanks in advance!
Related
how to watch the array value of ng-model in angularjs i have created fiddle but does not work Please take a look and suggest.
Thanks
<div ng-app ng-controller="ParentCtrl">
<div ng-controller="ChildCtrl">
<table>
<tr ng-repeat="user in profiles track by $index">
<td>
<input
type="text"
name="parktime_{{user.user_id}}"
ng-model="orderItems[user.user_id].parktime"
>
</td>
</tr>
</table>
</div>
</div>
function ParentCtrl($scope) {
}
function ChildCtrl($scope) {
$scope.parkOptions = {};
$scope.profiles = [
{user_id: '01', park_name: 'England Park'},
{user_id: '02', park_name: 'France Park'}
];
$scope.orderItems = {};
$scope.orderItems.parktime = "Test";
$scope.$watch('orderItems[profiles.user_id].parktime', function(newVal, oldVal){
console.log(newVal);
})
}
http://jsfiddle.net/w5vskLfc/59/
I suggest you use ng-change instead. You can't use watch this way, it is to watch a single property instead.
I've also updated your model to use ng-init. This is something you should be careful with using, but in your case, you need to have an key defined at each position of your orderItems object. If you will always statically assign these, I recommend iterating through them once and creating a key that way instead.
HTML
<input type="text" name="parktime_{{user.user_id}}"
ng-init="orderItems[user.user_id] = {}"
ng-model="orderItems[user.user_id].parktime"
ng-change="onChange(user.user_id)">
JS
$scope.onChange = function(items) {
console.log(items);
}
You are trying to access indexes which does not exist. profiles is an array of objects and I don't think there is anything available on profiles.user_id index. Also, I don't think orderItems[profiles.user_id] will work as that index also doesn't exist.
Is there a way to tell ng-model if your value is 0 then show the placeholder value not the ng-model value.
The reason for this is I have an issue where the UX requires the ng-model to be one value while the business logic requires it to be another.
Something like this.
Controller
$scope.qty = 0;
//...some calculation that requires $scope.qty to be a number
HTML
<input ng-model="qty" placeholder="N/A">
<!-- This will show 0 not N/A as qty has a value-->
I do understand you can edit the functionality of ng-model with the following.
ng-model-options={getterSetter: true}
This does solve this issue in a single ng-model like above but what about when the qty is in a ng-repeat?
In the real world we are making a page that auto calculates the amount of items a user should order based on there inventory. If the inventory is 0 the placeholder is used if it is changed by the user then the value they entered in is used.
As there is more then one product they can order we have this in an ng-repeat.
Controller
$scope.products = [{
//...product data
inventory : 0
}]
HTML
<tr ng-repeat="product in products track by $index">
<td>
<input ng-model="product.inventory" placeholder="N/A">
</td>
</tr>
You can try the setter getter method but as the only value you get is the value entered into the input box you lose the context of which item the user is referring to unless you create a setter getter function for each product.
Try this. You can define a getter function for ng-model directive if you use ng-model-options by setting getterSetter as true. ng-model-options is used to modify the behaviour of ng-model.
<input ng-model="getterSetter" placeholder="N/A" ng-model-options={getterSetter: true}>
// Controller function
$scope.getterSetter = function(value) {
if(value == 0) {
return "N/A";
}
else {
return value;
}
}
You can ngModelOptions, Object to tell Angular exactly when to update the Model.
<input ng-model="updateModel" placeholder="some text" ng-model-options={updateModel: true}>
// Controller method
$scope.updateModel= function(value) {
if(value <= 0) {
return "some text";
}
else {
return value;
}
}
How can I reset the value of an ng-model in the controller after an ngChange without using a directive
<div ng-repeat="i in items">
<!-- Some DOM comes here -->
<select ng-model="i.avail" ng-change="changeAvail(i.id, i.avail)">
<option value="true">Available</option>
<option value="false">Unavailable</option>
</select>
<!-- More DOM follows -->
</div>
The Javascript in the controller is as follows
$scope.changeAvail = function(itemId, value){
if(confirm("You cannot undo this action")){
//Send an ajax request to backend for an irreversible action
}
else{
//Restore input to initial value;
}
}
I wouldn't want to implement a directive just for this single occurence
You should Ideally store old value of items inside scope & do use them later to revert back to original one.
$scope.loadItem = function(){
$http.get('/api/getitems').then(function(response){
$scope.items = response.data;
$scope.oldCopy = angular.copy($scope.items); //do it where ever you are setting items
});
}
Then do send whole item to ng-change method like ng-change="changeAvail(i)"
$scope.changeAvail = function(item){
if(confirm("You cannot undo this action")){
//save object
$http.post('/api/data/save', item).then(function(){
//alert('Date saved successfully.');
$scope.loadItem(); //to update items from DB, to make sure items would be updated.
})
}
else{
//get current old object based on itemId, & then do revert it.
var oldItem = $filter('filter')($scope.oldCopy, {itemId: item.itemId}, true)
if(oldItem && oldItem.length){
item = oldItem[0]; //filters return array, so take 1st one while replacing it.
}
}
}
I was wondering how to get access to the $scope value from an input box, which happens to be in an ng-repeat, inside of the controller.
View
<div ng-repeat="item in items track by $index">
<form ng-submit="addItem(item, $index)">
<input ng-model="newItem.value" type="text"></input>
</form>
</div>
Controller
$scope.addItem = function(item, index) {
var itemVal = $scope.newItem.value;
console.log(itemVal);
}
The main problem is that I can't access the value from either of the input boxes inside of the controller.
code has been simplified for this quesiton
Really appreciate any help. Thanks
I believe you have only single value, which you want to show inside ng-repeat then Do initialize newItem inside controller like
$scope.newItem = {}
Because of newItem initialization on controller level, ng-repeat will never create a new child scope for it, it will reuse the one parent has created.
If you need one input per item, you need to keep one new model for each item somewhere.
If items is a list, you can keep these newItems in a separate list (jsfiddle):
View
<div ng-repeat="item in items track by $index">
<form ng-submit="addItem(item, $index)">
<input ng-model="newItems[$index]" type="text"></input>
</form>
</div>
Controller
$scope.newItems = [];
$scope.addItem = function(item, index) {
var itemVal = $scope.newItems[index];
console.log(itemVal);
}
Hi Im attempting to build functionality around the length of a filter in angularjs, and although its working as it should in the view, in the controller the variable seems to stay outdated...
When I click on the div below it filters a list and calls the filterby function. The output of the length of the newly filtered list updates in the view correctly. However in the function itself I have a log set and it is still showing the old length when I click on the div.
<div ng-repeat="filter in filters" ng-click="filterby(filter.filter_type)">{{filter.filter_type}}</div>
<ul>
<li ng-repeat="event in filtered = (events | filter:query) | orderBy:'-event_date' ">
<span >{{event.event_date}},{{event.event_name}}, {{event.event_venue}}, {{event.event_description}} </span>
</li>
</ul>
<br />Length of filtered items {{filtered.length}}
And my view....
$scope.filterby = function(filterby) {
if (filterby == 'ALL') {
$scope.query = '';
}
else {
$scope.query = filterby;
}
console.log($scope.filtered.length);
};
My filter data:
$scope.filters = [
{'filter_type' : 'ALL'},
{'filter_type' : 'Macnass'}
];
EDIT: Ok its not that it nots working at all, its just showing the previous value, as if its one click behind all the time, so its something to do with the fact that the variable in the view is updated after the list is made. but Im not sure how to go about insuring the variable in the controller is the latest value.
Plunker: http://plnkr.co/edit/u7KpqYx8gDwaaXEvGeMn?p=preview
check out the plunker
added below
$scope.filtered = $filter('filter')($scope.events, $scope.query)
in $scope.filterby function