ng-option select bound to separate array - arrays

I have a product model that has a property I want to bind to a separate array of options. Basically by product model has a property called 'category', like this:
productModel = {
Id : 1,
Description: 'Widget',
Category: 0,
...
As you can see, the property is an int (from the db) but I also get a separate array of what the categories are:
Categories : [
{ "Number" : 0, Name : "N/A" },
{ "Number" : 1, Name : "Option 1" },
{ "Number" : 2, Name : "Option 2" }
]
I want to be able to have a select list with the corresponding value shown, so if the product model comes back with 0 set then the default value in the select list will be "N/A".
I have achieved this by doing:
<select ng-model="Categories[productModel.Category]" ng-options="v.name for v in Categories" ...
but the problem with this is that when I change the option the value isn't binding back to the model. Because the data is posted back the server when the user changes the value I don't really want to change the productModel to have the same Name and Number structure as the categories (I can do this if it is the best way). I really just want the user to be able to select an option and for the product model to contain the corresponding number.
Can I (should I) do this using the 'track by'?

You need to update your ng-model value to bind to productModel.Category, you also need to update your ng-options expression to the following ng-options="v.Name as v.Number for v in categories".
You can find more information regarding the ng-options and ng-model directives here.
Please see working example here
HTML:
<div ng-controller="TestController">
<select ng-model="productModel.Category" ng-options="v.Name as v.Number for v in categories"></select>
<h3>productModel.Catecogy => {{productModel.Category}}</h3>
</div>
JS:
var myApp = angular.module('myApp', []);
myApp.controller('TestController', ['$scope', function($scope) {
$scope.productModel = {
Id: 1,
Description: 'Widget',
Category: 0
};
$scope.categories = [{
"Number": 0,
Name: "N/A"
}, {
"Number": 1,
Name: "Option 1"
}, {
"Number": 2,
Name: "Option 2"
}];
}]);
Not relevant to the question but its good practice to try and keep the case of your properties and variable names the same.

Related

Angular how to have multiple selected

I have this array of objects. that holds somethings like this.
[
{
id: 1,
name: "Extra Cheese"
},
{
id: 2,
name: "No Cheese"
}
]
im iterating thru the array here
<select ng-model="item.modifiers" multiple chosen class="chosen-select" tabindex="4" ng-options="modifier._id as modifier.name for modifier in modifiers"></select>
The thing item.modifiers model that has an array of this 2 id
[
1,2
]
I want the multi select to auto selected the two ids that are in the item.model
I want the final result to look something like this
Your code is pretty much working already, maybe some of the variables are not assigned correctly (eg. id instead of _id)
angular.module('test', []).controller('Test', Test);
function Test($scope) {
$scope.modifiers = [
{
id: 1,
name: "Extra Cheese"
},
{
id: 2,
name: "No Cheese"
}
]
$scope.item = {};
// add this for pre-selecting both options
$scope.item.modifiers = [1,2];
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
<div ng-app='test' ng-controller='Test'>
<select ng-model="item.modifiers" multiple chosen class="chosen-select" tabindex="4" ng-options="modifier.id as modifier.name for modifier in modifiers"></select>
</div>
If I understand the question correctly, you're wanting to pre-select the two options.
To do this you will need to set your ng-model to point to the actual objects you are iterating over.
You will also need to change your ng-options to ng-options="modifier as modifier.name for modifier in modifiers" rather than just iterating over the ids.
Here's the relevant documentation under Complex Models (objects or collections)
https://docs.angularjs.org/api/ng/directive/ngOptions
Something like this should work:
HTML:
<select ng-model="$ctrl.item.modifiers"
ng-options="modifier as modifier.name for modifier in $ctrl.modifiers"
multiple chosen class="chosen-select" tabindex="4" >
</select>
JS:
app.controller("my-controller", function() {
var $ctrl = this;
$ctrl.modifiers = [{
id: 1,
name: "Extra Cheese"
}, {
id: 2,
name: "No Cheese"
}];
$ctrl.item = {
modifiers: []
}
$ctrl.$onInit = function() {
const id1 = 1;
const id2 = 2;
for (const modifier of $ctrl.modifiers) {
if (modifier.id === id1 || modifier.id === id2) {
$ctrl.item.modifiers.push(modifier);
}
}
}
}
Here's a pen showing the result:
http://codepen.io/Lahikainen/pen/WooaEx
I hope this helps...

how to filter a list through a dropdown?

I am trying to filter a list by a property that is set by a dropdown:
<select ng-model="filterItem" ng-options="item.name for item in filterOptions.stores">
</select>
This is the the data for the dropdown:
$scope.filterOptions = {
stores: [
{id : 2, name : 'Show All', rating: 6 },
{id : 3, name : 'Rating 5', rating: 5 },
{id : 4, name : 'Rating 4', rating: 4 },
{id : 5, name : 'Rating 3', rating: 3 },
{id : 6, name : 'Rating 2', rating: 2 },
{id : 7, name : 'Rating 1', rating: 1 }
]
};
The filter is actually not working properly through the rating property: it returns more that just the one selected property:
<li data-ng-repeat="item in data | filter:filterItem.rating" >
Name: {{item.name}} Price: {{item.price}} Rating: {{item.rating}}
</li>
How can I fix the filter here?
This is a plunkr:http://plnkr.co/edit/vAebEb?p=preview
Right now you are setting filterItem.rating as the filter, so you're setting a string as the filter. From docs (https://docs.angularjs.org/api/ng/filter/filter):
The string is used for matching against the contents of the array. All
strings or objects with string properties in array that match this
string will be returned. This also applies to nested object
properties. The predicate can be negated by prefixing the string with
!.
What this is doing is matching ANY property in your array with the value filterItem.rating; so product's with the number in their product name are also being matched.
Since you want the filter to ONLY apply to the rating property, you want to set an object like this:
<li data-ng-repeat="item in data | filter:{rating:filterItem.rating}" >
That will now filter properly, but Show All doesn't work properly since filterItem.rating is undefined when it's show all. Since we don't want the filter to apply when Show All is selected, you can check for the filterItem.rating property first:
<li data-ng-repeat="item in data | filter:filterItem.rating && {rating:filterItem.rating}" >
I've updated your Plunkr here: http://plnkr.co/edit/q5Ns8c6HN1eIGZANlI4s?p=preview
You need to make a couple of changes:
In your $scope.filterOptions.stores object: Remove the rating for Show All option like:
{id : 2, name : 'Show All'},
In your html where you are using filter:
<li data-ng-repeat="item in data | filter:filterItem.rating && {rating:filterItem.rating}">
Hope this helps.

filtering the list using angularjs

See my Fiddle
I have list of books label with "comic" and "fiction" in my list.
on top I have all label and if you click on each label then books labled with that text should only be displayed.
If I get the JSON key at parent level in JSON then it works perfect.
but in this case I have label key as cid and I need to sort basic on that key.
this is my js code
function Test($scope) {
$scope.persons = [{
"s": "book1",
"cl": [{
"cn": "fiction",
"cid": 1
}]
}, {
"s": "book 2",
"cl": [{
"cn": "comic",
"cid": 2
}]
}];
}
any idea?
You can use ng-click in each tab and call a function with a value .based on that value you can filter the array to new array.
like this
<span ng-click="setTab(1)">fiction</span> |
<span ng-click="setTab(2)">comic</span> |
<span ng-click="setTab(3)">No filter</span>
and in controller
$scope.setTab = function(a) {
$scope.s=a;
//filter your array based on the value
/*if(a===1){ filter fictions} and so on */
}
see my fiddle for starting

Refine selection of multiple select elements with array of objects using ng-options

Say I have an array of objects:
var people = [
{name: "person 1", favouriteThing: 'pizza'},
{name: "person 1", favouriteThing: 'vegetables'},
{name: "person 2", favouriteThing: 'spinach'},
{name: "person 2", favouriteThing: 'kimchi'},
];
I want to be able to refine this data with select elements so that the first element would only contain 'person 1' and 'person 2' as options (no duplicates). After 'person 1' is selected, pizza and vegetables should be available in the second select element.
Here's what I currently have for the select elements:
<select ng-options="person.name for person in people" ng-model="name"></select>
<select ng-options="person.favouriteThing group by name for person in people"></select>
Just hoping for some input on the approach I should take. Maybe I should be using an object more like this? (not ideal for my situation)
var people = [
{name: "person 1",
favouriteThings: ['pizza', 'vegetables']
},
{name: "person 2",
favouriteThings: ['spinach', 'kimchi']
}
];
Created a plnkr
you can have two solution
(1) Load single select with group by 'name' property.
<select ng-options="person.favouriteThing group by person.name for person in c.people" ng-model="name"></select>
(2) Load two different select. One with name and one with favoriteThing. On change of name you can load favorite thing.
<select ng-options="person.name for person in c.getPeopleName()" ng-model="personName"></select>
<select ng-options="person.favouriteThing for person in c.getFavoriteThing(personName)" ng-model="favoriteThing"></select>
this.getPeopleName = function () {
return _.uniq(this.people, function (item) {return item.name;})
};
this.getFavoriteThing = function (people) {
var arr = [];
_.each(this.people, function (item) {
if(item.name === people.name) {
arr.push(item);
}
});
return arr;
};
To get the unique value use undrescore,
$scope.personName =_.uniq(people, function(person) { return person.name; });

AngularJS Select and ng-options: Can I bind and object to ng-model while only displaying a property?

I'm binding a select element to data that looks like this:
var gearConditions = [
{ id: 1, value: 'New' },
{ id: 2, value: 'Like New' },
{ id: 3, value: 'Excellent' },
{ id: 4, value: 'Good' },
{ id: 5, value: 'Fair' },
{ id: 6, value: 'Very Used' },
{ id: 7, value: 'Other' }
];
My select looks like this:
<select name="condition"
class="form-control"
ng-model="postModel.condition"
ng-options="condition.id as condition.value for condition in gearConditions">
</select>
This binds condition.id to the ng-model and displays condition.value as the select option. My question is: can I keep the current behavior but bind the whole object to the ng-model?
For example if the first option is selected the model value would then be {id:1, value: 'New'} rather than just 1.
Is this possible or do I need to use ng-changed to accomplish this?
Thanks!
Yes, change condition.id to condition:
ng-options="condition as condition.value for condition in gearConditions"
I think you you try similar:
// I took this from my code
ng-options="key as value for (key, value) in ...
Now you could try to combine key+value and see if it appears like you wish.

Resources