Hardcoded values in NG-OPTIONS with dynamic values from NG-REPEAT - angularjs

Let's say we have this data and it's being returned by an API
$scope.arrayOfStudentObjects = [
{ name : 'Ashley', gender : 'female' },
{ name : 'Tom', gender : 'male' },
{ name : 'Scott', gender : 'male' }
];
Then the values that we put in < select > are in a scope
$scope.gender = [ { type : 'male' }, { type : 'female' } ];
Now we want to display the values and correctly set the selection for the gender in the select dropdown
<tr ng-repeat="student in arrayOfStudentObjects track by $index">
<select ng-model="student.gender" ng-options="sex.type for sex in gender"></select>
</tr>
However, I'm not sure why it's not displaying/selecting the proper gender for that student. Please see Plunker. http://plnkr.co/edit/o0Wt2Qg8BFXmeeMqFBIE?p=preview

change your <select...> to
<select ng-model="student.gender" ng-options="sex.type as sex.type for sex in gender"></select>
otherwise the value it compares to is the full object.
forked plunk:
http://plnkr.co/edit/azBhpIEUkybXmQWliMOR?p=preview

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...

AngularJS orderby sorts number and dates treating them as string

I need to develop a table in angular js to show a third party data (and hence data cannot be changed).
Data to be shown is completely dynamic in that number or sequence of columns can change anytime.
The value to be displayed may be a number or a string or a date, which is governed by the third party data.
I need to sort table on clicking on any of the headers
I am aware of some techniques like using | number filter etc, but it does not seem to work in this dynamic environment
Hence I need to make my table as completely dynamic.
However I am facing issues in using order by as it sorts even numbers and dates treating them as string.
<table>
<td ng-repeat="key in keys(Header[0])" ng-click="maintainOrder(key)" >
<span>{{Header[0][key]}}</span>
</td>
<tr ng-repeat="singleRow in data | orderBy:orderByCriteria:reverseSort" >
<td ng-repeat="key in keys(data[0])" >
{{singleRow[key]}}
</td>
</tr>
</table>
$scope.maintainOrder = function(key)
{
$scope.orderByCriteria = key;
$scope.reverseSort = ! $scope.reverseSort;
};
$scope.keys = function(obj){
console.log((Object.keys(obj)));
return obj? Object.keys(obj) : [];
};
$scope.data= [
{
"quantity" : "85",
"type" : "mango",
"expiryDate" : "15/09/2015"
},
{
"quantity" : "9",
"type" : "orange",
"expiryDate" : "5/07/2015"
},
{
"quantity" : "66",
"type" : "apple",
"expiryDate" : "25/09/2015"
},
{
"quantity" : "95",
"type" : "mango",
"expiryDate" : "31/08/2015"
}
];
$scope.Header= [
{
"quantity" : "Qty ",
"type" : "Type",
"expiryDate" : "Expiry_Date"
}];
I have included a fiddle for the same:
fiddle link
You can create your own custom sort filter, and use the angular built-in functions angular.isNumber, angular.isDate, angular.isString
An example of a custom filter is here: http://jsfiddle.net/av1mLpqx/1/
In your custom filter, use a custom sort function like this:
array.sort(function (a, b) {
if (angular.isNumber(a) && angular.isNumber(b)) {
return a - b;
}
else if (angular.isDate(a) && angular.isDate(b)) {
return a.getTime() - b.getTime();
}
else if (angular.isString(a) && angular.isString(b)) {
return a.localeCompare(b);
}
else {
console.log("types unknown");
return 0;
}
}

ng-option select bound to separate array

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.

convert column value to a map value in ng-repeat

Nervous to ask this question.. HATE getting downvoted.. but it is what it is, I've searched and can't find the solution.
What I ended up doing is adding a loop that goes through my searchResults and reassigns the value for the column after the service returns inside the success block (PSEUDO CODE HERE, I can't copy and paste my actual code, there is an airgap):
var myNumberMap = {
1: "Number ONE!!",
2: "Number TWO!!",
3: "Number THREE!!!"
}
$scope.getSearchResults = function() {
$q.all({
resultSet : searchService.getSearchResults()
}).then(function(resultData) {
searchResults = resultData.resultSet;
for(var i = 0; i < searchResults.length; i++) {
searchResults[i].number = myNumberMap[searchResults[i].number];
}
}
}
I was really hoping there was some slick way I could just assign the data result value inside the grid config to be the value in the map?
Something like:
$scope.myCoolGridConfig = NgGridConfig.getConfig(
NgGridConfig.getDefaultConfig(), {
data: 'searchModel.searchResults.list',
columnDefs: [
field: 'number',
displayName: 'Number',
value: myNumberMap[searchModel.searchResults.list.number]
]
}
)
There are a few methods that you could take here:
Create a custom filter that you apply to your ng-repeat to transform the values based on your map.
Store your value map in your angular controller and bind the mapped value to the DOM.
// Controller
$scope.myMap = {
1 : "String One",
2 : "String Two",
3 : "String Three"
}
// something.html
<div ng-repeat='num in numList'>
{{myMap[num]}}
</div>
If I interpenetrated the question correctly your looking for something along these lines.
myMap = {
1 : "String One",
2 : "String Two",
3 : "String Three"
};
If the col number is 1 display String One instead of one in the table
Use myMap and look for the prop of col in it to pull the string value
<table>
<tr ng-repeat="col in tempCols">
<td>{{col}}</td>
<td>{{myMap[col]}}</td>
</tr>
</table>
If you need to do it towards an object that has no defining index such as the object below.
$scope.objectData = [{
name: "test1",
},
{
name: "test1",
},
{
name: "test1",
},
{
name: "test1",
},
{
name: "test1",
},
]
You can track it by $index + 1
<table>
<tr>
<td> Column Converted</td>
<td> Object name value</td>
<tr ng-repeat="col in objectData">
<td>{{myMap[$index + 1]}}</td>
<td>{{col.name}}</td>
</tr>
</table>
Heres a plunker for a better visual

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.

Resources