I have an angular grid (ng-grid) where one ove the columns has a dropdown which is bound to a property of the objects displayed in the rows.
<div class="gridStyle span9" ng-grid="gridOptions"></div>
$scope.types = ['cat', 'dog' 'rat'];
$scope.gridOptions = {
data : 'AnimalData',
columnDefs : [{
field : 'name',
displayName : 'Name'
}, {
field : 'birthday',
displayName : 'Birthday'
},{
field : 'type',
displayName : 'type'
cellTemplate : 'cellTemplate.html'
}]
};
cellTemplate.html:
<div>
<select ng-model="AnimalData[ row.rowIndex ].type">
<option ng-repeat="item in types">{{item}}</option>
</select>
</div>
This binds to my objects perfectly well but when I order my grid the dropdowns do not order they just stay in the same place with the values not changing. How would i go about fixing this?
Ok, found the issue. To reference the original object you need to change
AnimalData[ row.rowIndex ].type to row.entity.myEditableProperty.type
eg:
<div><select ng-model="row.entity.myEditableProperty.type" ng-options="item for item in types"></select></div>
Proof of concept Plunkr: http://plnkr.co/edit/i7vXng?p=preview
Related
I am having the hardest time getting two way binding to work for SELECT elements. I am trying to change the selected element programmably. I've found several Stackoverflow examples for binding the change event for SELECT, but I've not been many going the other way, where your application code changes the selected element.
There have been a few that I've found that use ng-repeat on an OPTION element but I've a) not been able to get it to work, and b) does not seem to be the "Angular Way".
HTML Code:
<div ng-controller="SIController">
<select id="current-command" ng-model="currentCommand"
ng-options="c as c.label for c in availableCommands track by c.id"></select>
<button ng-click="changeSelectedOption()">Select "open"</button>
Controller Code:
var myApp = angular.module('myApp', []);
function SIController($scope) {
$scope.availableCommands = [
{id: 'edit', label: 'Edit'},
{id: 'open', label: 'Open'},
{id: 'close', label: 'Close'}
];
$scope.currentCommand = "close";
$scope.changeSelectedOption = function() {
$scope.currentCommand = 'open';
};
};
I can verify that $scope.currentCommand is changing when the button is clicked, but the OPTION does not seem to be getting selected.
Fiddle here
Is there the working fiddle : http://jsfiddle.net/bzhkkw18/9/
To explain what I've done, there is the name of the function which didn't match on the ng-click and in the controller.
And the main part was the definition of your option. In your ng-options you set the all object. If it's what you really want, you have to do the same in your currentCommand like this :
//Object 2 is close
$scope.currentCommand = $scope.availableCommands[2];
I recently had a similar problem. Take look at my answer. You should modify the way you defined ng-options.
function MyCtrl($scope) {
$scope.values = [
{name : "Daily", id : 1},
{name : "Weekly", id : 2},
{name : "Monthly", id : 3},
{name : "Yearly", id : 4}];
$scope.selectedItem = $scope.values[0].id;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.min.js"></script>
<div ng-app ng-controller="MyCtrl">
<select ng-model="selectedItem" ng-options="selectedItem.id as selectedItem.name for selectedItem in values"></select>
selectedItem: {{selectedItem}}
</div>
When I bind the select elements to ng-model family, which refers to an element of font.families array, Angular doesn't bind what is selected. The array stays empty, with just the first null element.
But when I bind the select elements to font.families[$index], the binding is effective.
// Javascript
$scope.font.families = [null]; // Used to create an empty first line in the form
$scope.families = [
{ name: "Foo", parent: "Bar" },
{ name: "Doo", parent: "Dar" }
];
$scope.mainFamilies = [
{ name: "Bar", children: ["Foo", "Baz"] },
{ name: "Dar", children: ["Doo", "Hoo"] }
];
<!-- HTML -->
Font families : {{ font.families }}
<div ng-repeat="family in font.families track by $index">
Family : {{ family }}
<ng-form name="familyRow">
<select ng-options="fam as fam.name group by fam.parent for fam in families"
ng-model="font.families[$index]"
name="family">
<option disabled value="">—</option>
</select>
<select ng-options="mainFam.name as mainFam.name for mainFam in mainFamilies"
ng-model="font.families[$index].parent"
name="mainFamily">
<option disabled value="">—</option>
</select>
</div>
Plunker to illustrate the problem.
How comes?
Here's my understanding of the issue:
Case 1 (Working): You're using ng-model="model.families[$index]". In this case when you make a selection here's what happens:
model.families[0] -> Your selection
Case 2 (Not working): You're using ng-model="family". In this case this is what is happening:
family -> model.families[0] -> null
When you make the selection:
family -> new selection
model.families[0] -> null
The problem is that in 2nd case, the assignment causes the family variable to be assigned a new value altogether and the source array remains the same.
You can further verify this by adding these statements in your html:
family: {{family}}
model.families: {{model.families[$index]}}
Are they equal?: {{familly === model.families[$index]}}
I have object product = {id: "759", name: "someName", category_id: "139", cartridge_type: 2 ...} in my angular controller.
Why preselected option in ngOptions doesn't work? Select renders empty option as if product.cartridge_type would be null.
HTML
<select class="form-control"
id="cartridge_type"
name="cartridge_type"
ng-init="product.cartridge_type=product.cartridge_type||cartridgeTypeScope[0]"
ng-model="product.cartridge_type"
ng-options="cartridge_type.id as cartridge_type.name for cartridge_type in cartridgeTypeScope">
<option value="">Select type</option>
</select>
JS
$http.get('someApiPath').success(function(data) {
$scope.product = data[0];
console.log( $scope.product );
});
$scope.cartridgeTypeScope = [
{
id: 0,
name : '-'
},
{
id: 1,
name : 'cartridgeType1'
},
{
id: 2,
name : 'cartridgeType2'
}
]
Just simple use cartridgeTypeScope[0].id in ng-init
ng-init="product.cartridge_type=product.cartridge_type||cartridgeTypeScope[0].id"
Thing is that you are using cartridge_type.id as cartridge_type.name which is expecting id in the select but in ng-init you are providing it complete object (cartridgeTypeScope[0]).
So it is not selecting your option value.
Alternatively you can do
You can use same ng-init but remove cartridge_type.id as from your ng-options
ng-init="product.cartridge_type=product.cartridge_type||cartridgeTypeScope[0]"
ng-options="cartridge_type.name for cartridge_type in cartridgeTypeScope"
Hope It help :)
UPDATE
For controller default option you need to do
$scope.product={
"cartridge_type":2
}
UPADTE 2:-
For $http:-
Plunker
Without JQuery I'd like to be able to hide certain form input fields when a selection is made in the <select> drop down menu.
Similar to this behavior, but with ng-repeat. And a little more dynamic, making ng-hide use some sort of isHidden function calling the ng.models attributes, comparing to the selected value
Here's my attempt: http://jsfiddle.net/Td2NZ/260/, with the ng-hide being ng-hide="address.state === 'FL'"
the === FL part is hardcoding "FL", but I'd like that to draw from the input that is being repeated in ng-repeat.
Fiddle: http://jsfiddle.net/Td2NZ/261/
A couple things to note: the way to determine if something is hidden should be a property of the input to be hidden, not the select menu option. You had an attribute in the drop down affects: xxx, now that is an attribute of the input: hiddenBy: xxx. Also to hide the label as well the ng-hide has been moved to the <div> tag. This should get you started. Another resource that helped solve this problem was http://plnkr.co/edit/SxIvt4KThWLtWvh3PnOh?p=preview
The JSFiddle you provided almost works, if you want it to work with hardcoded "FL" change === to ==.
=== checks type and value, where you really want to just check value is equal. It is best practice to always use ===, but in this scenario you should use ==.
angular
var myApp = angular.module('myApp', []);
myApp.controller('MyCtrl', function($scope) {
$scope.addresses = [
{'state': 'AL'},
{'state': 'CA'},
{'state': 'FL'}
];
$scope.lov_state = [
{'lookupCode': 'AL', 'description': 'Alabama'},
{'lookupCode': 'FL', 'description': 'Florida'},
{'lookupCode': 'CA', 'description': 'California'},
{'lookupCode': 'DE', 'description': 'Delaware', 'affects': 'hidden'}
];
$scope.inputs_text = [
{label: "Start Date", input:'yyyy-mm-dd', name:'dat_start', isRequired: "true"},
{label: "End Date", input:'yyyy-mm-dd', name:'dat_end', isRequired: "true"},
{label: "hide_for_FL", input:'wow', name:'hidden', isRequired: "true", hiddenBy: 'FL'}
];
$scope.isHidden = function(){
return message = (address.state === 'FL');
};
});
html
<div ng-controller="MyCtrl">
<div>Billing State:
<select ng-model="address.state" ng-options="state.lookupCode as state.description for state in lov_state" ng-init="address.state=1"></select>
<p> address.state: {{address.state}}</p>
</div>
<br> <tt>State selected: {{address.state}}</tt>
<div ng-repeat="input in inputs_text" ng-hide="(input.hiddenBy == address.state)">
<label>{{input.label}}</label>
<input name="{{input.name}}" id="{{input.name}}" ng-model="input.input" ng-require="input.isRequired"></input> <!-- function -- find address.state in the array, when match found get affects option and if it equals input.input return true -->
<p> Input: {{input.input}}</p>
</div>
</div>
I've been reading a lot on angular scopes and inheritance but I can't get my head around this problem. Here is the HTML I'm using:
<div class="sensorquery-sensor" ng-repeat="sensor in query.sensors" ng-controller="SensorsCtrl">
<select class="form-control"
ng-model="selected.sensor"
ng-options="sensor.name for sensor in parameters.sensors">
</select>
<select class="form-control"
ng-model="selected.definition"
ng-options="definition.value for definition in definitions">
</select>
<select class="form-control"
ng-model="selected.operation"
ng-options="operation for operation in operations">
</select>
</div>
As you can see, I have an ng-repeat based on query.sensors. The values stored in this query.sensors array should be simple:
{
name: 'sensor1',
type: 'temperature'
}
But I want to use a child controller: SensorsCtrl to handle more logic per sensor and hide the complexitiy of sensors. A sensor can look like:
{
name: 'sensor1',
attributes: [
'model',
'brand'
],
definitions: [
{
datatype: 'double',
value: 'temperature'
},
{
datatype: 'integer',
value: 'pressure'
},
{
datatype: 'string',
value: 'color'
}
]
}
So it's in my SensorsCtrl controller where I want to put the selection logic:
$scope.$watch('selected.sensor', function(sensor) {
$scope.definitions = sensor.template.definition;
});
$scope.$watch('selected.definition', function(definition) {
if (definition.datatype === 'string') {
$scope.operations = ['Count'];
} else {
$scope.operations = ['Max', 'Min'];
}
$scope.selected.operation = _.first($scope.operations);
});
How do I keep the link with the parent query.sensors[$index] while transforming the sensor as the user selects different sensors and definitions?
Setting up a watcher on selected and updating the query.sensors array triggers an infinite $digest loop.
I found the solution which was right before my eyes:
<div class="sensorquery-sensor" ng-repeat="sensor in query.sensors" ng-controller="SensorsCtrl">
<!-- ... -->
</div>
The sensor is a reference to the original object of the parent query.sensors. An it's created in the scope of the sub-controller.
So in my SensorsCtrl controller, I can just watch:
$scope.$watch('sensor.definition', function(definition) {
/* ... */
});
So I can put hide some complexity in this controller while maintaining a proper link to the original element.
It does not answer the question of maintaining a less complex object but it's a different question I guess.