How to make angular child scopes refresh? - javascript

I have a template:
<div class="oss-object cp-def cp-row" ng-repeat="(key, value) in data" ng-init="viewables = getViewables(value.versions[0].objectInfo);">
<div class="cp-def">
{{value.info.name}} OssStatus: {{value.versions[0].objectInfo.status}}
, 3D-Viewables:
<select ng-change="viewableSelected(value.versions[0].urn, viewables, '3d')" ng-model="viewables.selected3d" ng-options="viewable as viewable.name for viewable in viewables['3d']">
<option value="">---Please select---</option>
</select>
, 2D-Viewables:
<select ng-change="viewableSelected(value.versions[0].urn, viewables, '2d')" ng-model="viewables.selected2d" ng-options="viewable as viewable.name for viewable in viewables['2d']">
<option value="">---Please select---</option>
</select>
</div>
</div>
And when data gets updated (the data property used in the top ng-repeat) in my controller with a new data set, it doesn't automatically refresh the child scopes in the ng-options. which are derived from the data set. Does anyone know how to refresh child scopes? I have tried calling $apply and $digest but with no success.

As I said in the comments, you could try to replace viewables['3d'] in the ng-options with getViewables(value, '3d') and have the controller return the array.

If you look at the docs for ngInit, you'll see they basically say "never use this except in nested ngRepeats".
One way to do what you want is to create a controller for each repeated item, and create a $watch on the data that changes (or expression in this case), and set viewables equal to that.
eg
function ViewablesCtrl($scope){
$scope.$watch($scope.getViewables, function(){$scope.viewables = $scope.getViewables($scope.value.versions[0].objectInfo);}
})
--
<div class="oss-object cp-def cp-row" ng-repeat="(key, value) in data" ng-controller="ViewablesCtrl()">

Related

ng-model changes all select at once

jsfiddle
Hi.
I have a problem with my application. I have to write several selects by using ng-repeat and each of these selects must be filled with the same data.
The problem is, when the one is changed, others selects are changes to the same value - why?.
I suppose that the problem is in the ng-model - maybe I don't understand how the "hierarchy" of the ng-model works.
If the name of the ng-model is only "option" - it doesn't work!
If the name of the ng-model is "something.option" - it also doesn't
work!
If the name of the ng-model is "something.else.option" - it does work
but all selects are filled!
HTML:
<div ng-controller="MyCtrl">
<div ng-if="models" ng-repeat="m in models">
<br><label>{{m.model}} ({{m.no}})</label><br>
<select ng-model="models.m.opModel" ng-options="opt.value as opt.text for opt in options" ng-change="foo()"></select>
</div>
</div>
JS:
var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
$scope.models = [
{'no':'A', 'model':'alpha'},
{'no':'B', 'model':'beta'},
{'no':'C', 'model':'gamma'}
];
$scope.options = [
{'value':1, 'text':'one'},
{'value':2, 'text':'two'},
{'value':3, 'text':'three'}
];
$scope.foo = function(){
alert($scope.models.m.opModel);
}
}
What am I doing wrong?
Thanks a lot.
You've created a scope object called "m" which is the current child of the "models" list. So for each dropdown, you're going to have a different "m" scope object. This is what you need to bind to in your ng-model so that the dropdown is bound to its unique parent in the "models" list.
Change <select ng-model="models.m.opModel"> to <select ng-model="m.opModel" to fix the problem.
To access the value with the foo() function, you'll need to use this updated function:
$scope.foo = function(index){
alert($scope.models[index].opModel)
}
And update the <select> like this:
<select ng-model="m.opModel" ng-options="opt.value as opt.text for opt in options" ng-change="foo($index)"></select>
You're creating an ng-model called "opModel" in the ng-repeat which means you'll have three new opModels under $scope.models. This is an array you can access later using an index value to specify which of the $scope.models[].opModel you want to access.
Notice that I've changed the ng-change code to send the current $index which is basically an ng-repeat counter. So your foo() function will receive either a 0, 1 or 2 which lets us access the specific ngModel that we need to access.
You are binding to the single object models. Inside an ng-repeat the repeated is available "in scope". You probably want to change this code to:
<div ng-controller="MyCtrl">
<div ng-if="models" ng-repeat="m in models">
<br><label>{{m.model}} ({{m.no}})</label><br>
<select ng-model="m.opModel" ng-options="opt.value as opt.text for opt in options" ng-change="foo()"></select>
</div>
</div>
Look at the ng-model="m.opModel", that is what I've changed. You are now updating the value of the single item, and not inserting a new object into an array which is then reused by all the ng-repeat items (which is why all the values would update at the same time).

knock out foreach binding with independent varriable

I am using knockout for binding in my html5 application.
I have one strange scenario.
One div i am binding using for loop like below
<div data-bind="foreach: oneList">
<select name="dropDown1" id="dropDown1" data-bind="options: ddList,optionsText: function(item) { return item.value;},optionsValue:function(item) { return item.key; }">
</select>
<input type="text" id="newValue" data-bind="value : oneValue"/>
</div>
Here oneList is diffent varriable and ddList is a diffent varriable,both are independent varriable.
So when actual binding happens drop down does not get binded but input text is binded because oneList.oneValue is valid but oneList.ddList is not valid
Please let me know if my question is not clear
Without seeing your view-model it is quite hard to tell, but most probably there is no ddList property defined on items in the oneList list.
Inside a foreach binding the current binding context refers to the current item from the list so if you need to "go up" in the binding context to access a property which is on the same level as your onlist then you need to use $parent (or $root to access your main view-model).
A fixed options binding would look like this:
<select data-bind="options: $parent.ddList, optionsText:... " >

ng-option with static link option

How to add static option that represents a link to other page using ng-options.
<select class="form-control"
ng-model="person"
ng-options="person.name for person in persons">
</select>
I am using select element with ng-options with predefined list of persons, where person is an object. I tried to use ng-repeat instead but this approach does not work:
<select ng-model="person" onChange = "window.location.href=this.value">
<option value="#/home">Anywhere</option>
<option value="#/current" ng-repeat="person in persons">{{person.name}}</option>
</select>
Varibale $scope.person gets the value "#/current". In this case linking works, but ng-model fails. Variable $scope.person should represent the selected person.
What I am expecting is that $scope.person has selected value, unless user choose "Anywhere", in which case he should be redirected to another page.
"#/home" and "#/current" represent the url location. "#/home"is a home page and "#/current" is a current page. onChange event redirects user to home page or reloads current page.
So when user select "Anywhere" he should be redirected to home page. For any other option user´s page won´t be changed.
First of all you should not mix native js and angularjs unless you know what exactly going on.
Use ng-change instead of onchange and check the value if it is value of 'Anywhere'. If it is then route, otherwise do nothing. In your approach you're redirecting in both cases.
<select ng-model="person" ng-change="selectHandler()">
<option value="">Anywhere</option>
<option value="{{prsn}}" ng-repeat="prsn in persons">
{{prsn.name}}
</option>
</select>
$scope.selectHandler = function(){
if($scope.person == ''){
console.log("route to /home");
//ROUTE WITH $location.path
}
}
Here is a working FIDDLE for demo.
in your ng-repeat try, you wrote:
ng-model="person"
which doesn't exist (because you do ng-repeat="person in persons")
try
ng-model="persons"

Accessing the model inside a ng-repeat

I have a ng-repeat loop over processes. What I am trying to do is to add a new block to the current process via a form with select box. However, my problem is I cannot access the model inside the loop from the controller. I guess this is because a new scope is created in a ng-repeat loop.
Still I couldn't find a way to access model from controller. Here is html and javascript code pieces for you to understand problem better.
<div class="container" ng-controller="ProcessCtrl">
<div class="process" ng-repeat="process in processes">
<form class="form-inline" ng-submit="addBlock($index)">
<select ng-model="blockType">
<option value="1">type1</option>
<option value="2">type2</option>
<option value="3">type3</option>
</select>
<button type="submit">add</button>
</form>
</div>
</div>
angularjs controller
function ProcessCtrl($scope, $filter) {
//...
$scope.addBlock = function(index) {
alert($scope.blockType); // undefined
$scope.processes[index].blocks.push({type: $scope.blockType});
};
}
Yes, the problem is that the parent scope can not access the child scopes created by ng-repeat.
Modify addBlock to also pass up the blockType:
ng-submit="addBlock($index, blockType)"

Using AngularJS, how do I bind a <select> element to an attribute that updates via a service

I have a display controller and a management controller. Inside my display controller, I have a dropdown selector with the list of items that have been selected.
I can get the display area dropdown to update the list, adding items as they are added in the management controller, but I cannot figure out how to select the newest item in the dropdown.
<div ng-controller="MyDisplayCtrl">
<select ng-model="item" ng-options="i.name for i in items">
</select>
</div>
I have made a jsfiddle to illustrate my situation. Ultimately, though, my question is how to bind that ng-model="item" to a data source updated by a service.
http://jsfiddle.net/whtevn/mUhPW/2/
Well, it looks like I've found a pretty satisfactory answer to this.
I exposed the storage object itself through the controller
function MyDisplayCtrl($scope, ItemStore) {
$scope.items = ItemStore.items;
$scope.item = ItemStore.currentItem;
// expose the itemstore service to the dom
$scope.store = ItemStore
$scope.getItem = function(){
return(ItemStore.currentItem);
}
}
and then address the currentItem directly
<div ng-controller="MyDisplayCtrl">
<select ng-model="store.currentItem" ng-options="i.name for i in items">
</select>
</div>
http://jsfiddle.net/whtevn/Cp2RJ/3/
Try using ng-options:
<div ng-controller="MyDisplayCtrl">
<select ng-options="i.name for i in items"></select>
</div>
See: http://docs.angularjs.org/api/ng.directive:select

Categories

Resources