I am applying filters to get the data of a particular field through a dropdown, but when I select any option the filter applied elements get removed. How can I resolve it?
HTML code:
<body ng-controller="MyCtrl">
<div>
<label>Country filter</label>
<input type="text" ng-model="countryFilter" />
<label>Order by</label>
<select ng-model="selectedOrder">
<option ng-repeat="option in options">{{option}}</option>
</select>
</div>
<ul>
<li ng-repeat="detail in details | filter:{loc : selectedOrder}">{{ detail.country }}</li>
</ul>
</body>
JS code:
var app = angular.module('plunker', []);
app.controller('MyCtrl', function($scope) {
// order by options
$scope.options = ['1', '2', '3'];
// all countries
$scope.details = [{
id:1, country:'Finland', address:'Mainstreet 2',detail:[{
loc:'1'
}]
},{
id:2, country:'Mexico', address:'Some address',detail:[{
loc:'2'
}]
},{
id:3, country:'Canada', address:'Snowroad 45',detail:[{
loc:'3'
}]
}];
});
I want to filter through options and loc value. Where am I going wrong?
You don't need to write a custom filter.
Change your filter to: filter:{detail: {loc:selectedOrder}}
I added <option value=""></option> to the dropdown and set $scope.selectedOrder = ""; in order to show all countries by default.
Codepen
filter:{prop:value} returns objects which have property prop at first level, it does not watch in object deeper. (When usual filter without params does it)
Your objects in array details do not have 'loc' property. So nothing fits filter.
You can not filter by exact property of 2nd and deeper levels of object with standard angular filter. Implement your own or change data.
Related
I have a request that returns an array of objects based on a Provider selected. Like this:
data:[
0:
Producto:"Chiken",
Unidad: "box",
PrecioUnitario:"34334",
etc..
1:
Producto:"Chiken",
Unidad: "box",
PrecioUnitario:"200",
etc..
]
I'm displaying the data properly in a <select> tag
What I want is that if the user selects let's say "Carne Asada" all of the other properties of that selected child object are auto-selected on the rest of the fields, i.e:
Unidad text input should be "box" automatically, "precioUnitario" field should be 200.
Or visually:
Another thing is that it should display the value that the object has but it can be edited by the user.
Controller:
$scope.columns = [{colId: 'col1', producto:[], catidad:'', unidades:[], preunit:''}];
$scope.fact = {};
$scope.get_proveedor_prod = function(fact){
var data = {ProveedorID: fact.ProvID};
$http.post(URL + "/api/get_prod_by_provider.php",data).then(function(callback) {
$scope.products = callback.data;
});
}
View:
<md-input-container>
<select ng-model="fact.producto"
ng-options="item.ProductID as item.NombreProducto for item in products"
class="form-control selectformcc" required>
<option value="" disabled selected>Producto</option>
</select>
</md-input-container>
(I'm assuming your data notation is incorrect and that you meant to use an array of objects.)
Bind the select to the whole item instead of to a property of the item:
ng-options="item as item.NombreProducto for item in products" //not ="item.ProductID...
Now fact.producto (select model) is an object and will contain the whole item. In your Unidad text box you can use:
<input type="text" ng-model="fact.producto.Unidad" />
Here is an example with easy to understand data: Working Fiddle
I am new to AngularJS so please bear with me.
Following is the the JSON string I am trying to bind in the select element:
[
{"Name":"Value 1","ID":1},
{"Name":"Value 2","ID":2},
{"Name":"Value 3","ID":3},
{"Name":"Value 4","ID":4}
]
Following is the JS object for the same:
function NameValue(nameValue){
var self = this;
self.ID = nameValue.ID;
self.Name= nameValue.Name;
}
I am parsing the above JSON string, looping through the objects and pushing items into an array using the above JS object like:
angular.forEach(angular.fromJson(jsonString), function (value, key) {
$scope.Values.push(new NameValue(value));
});
Following is my select with agularjs bindings:
<select ng-model="SelectedName" ng-options="x.Name for x in Values">/select>
When I select a value in the select element, the entire NameValue object is getting set into the SelectedName property which is what I am trying to do.
Now when I try to set the SelectedName property dynamically, the value is not getting selected and an empty option element is getting added in the select element. I used the {{SelectedName}} to check the value when set dynamically and when I select the same value in the select element manually and both are {"ID":2,"Name":"DAO"} which are exactly same. What am I doing wrong here?
The syntax of ng-options is something like this.link
<select ng-options="item as item.label for item in items track by item.id" ng-model="selected"></select>
Suppose you have controller like this
app.controller('MainCtrl', function($scope) {
$scope.Values = [
{"Name":"Value 1","ID":1},
{"Name":"Value 2","ID":2},
{"Name":"Value 3","ID":3},
{"Name":"Value 4","ID":4}
];
$scope.SelectedByName='Value 2'; //Default setting drop down by Name property
$scope.SelectedById=4; //Default setting drop down by ID property
});
If you follow the below syntax then either name or Id property will be set to selected variable.
If you need default selection of drop down then you need to set the respective model in controller.(as above)
HTML :
<body ng-controller="MainCtrl">
By name :
<select ng-options="value.Name as value.Name for value in Values"
ng-model="SelectedByName" ng-change="Print()"></select>
Selected value is : {{SelectedByName}}
<br>
By ID :
<select ng-options="value.ID as value.Name for value in Values"
ng-model="SelectedById" ng-change="Print()"></select>
Selected id is : {{SelectedById}}
</body>
Demo plunker Click here
First of all - you should initialize SelectName in your $scope.
Next you can use:
ng-options="x.id as x.name for x in values"
Can you display {{values}} in your template and it's look good? Maybe you have a problem with redraw template when data is push into value. Check this way also.
here is a working snippet. i guess you didn't defined Values as an array, before pushing anything you have to define the variable as an array.
var app = angular.module('myApp', []);
function NameValue(nameValue) {
var self = this;
self.ID = nameValue.ID;
self.Name = nameValue.Name;
}
app.controller('myCtrl', function($scope) {
$scope.Values = [];
$scope.jsonString = [{
"Name": "Value 1",
"ID": 1
}, {
"Name": "Value 2",
"ID": 2
}, {
"Name": "Value 3",
"ID": 3
}, {
"Name": "Value 4",
"ID": 4
}];
angular.forEach(angular.fromJson( $scope.jsonString), function (value, key) {
$scope.Values.push(new NameValue(value));
});
console.log($scope.Values);
});
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<select ng-model="SelectedName" ng-options="x.Name for x in Values">/select>
</div>
</body>
</html>
I had the same issue and i found a solution:
Don't use ng-options but <option> tag
<select ng-model="..."> <option ng-repeat="..."> {{ ... }} </option></select>
I need to select option in combobox from ajax loaded data. That data comes as list of objects. The problem is that ng-option compares objects by reference and thus setting model to objects element results in appearing new empty option in combobox instead of selecting correct option.
The known workaround is to use track by expression.
And here is example code:
var myApp = angular.module("myApp", []);
myApp.controller("myCtrl", function($scope) {
$scope.roles =[
{ key:"administrator", value:"ROLE_ADMIN" },
{ key:"operator", value:"ROLE_OPERATOR" },
];
// this emulates data from server
// won't work without 'track by'
$scope.role={ key:"administrator", value:"ROLE_ADMIN" };
});
Template:
<body ng-app="myApp" ng-controller="myCtrl">
0: <input ng-model="roles[0].key" />
<br>
1: <input ng-model="roles[1].key" />
<br>
select role: <select ng-model="role" ng-options="r.key for r in roles track by r.value">
</select>
<pre>selected role={{role|json}}</pre>
</body>
Here another problem arises. When one selects role in combobox and then
changes it's "key" property in textbox, then selected role stays unchanged. So it looks like binding is suddenly gets broken.
https://jsfiddle.net/xLqackxw/8/
from Angular documentation https://docs.angularjs.org/api/ng/directive/ngOptions
<select ng-options="item as item.label for item in items track by item.id" ng-model="selected"></select>
So:
<select ng-model="role" ng-options="r as r.key for r in roles track by r.value"></select>
'$scope.role' value will be object like { key:"administrator", value:"ROLE_ADMIN" } or { key:"operator", value:"ROLE_OPERATOR" }
I have been working on this way too long trying to figure it out.
<select class="form-control"
ng-model="question.sel"
ng-change="updateDropDownQuestion(question,question.sel)">
<option ng-repeat="answer in question.answers" ng-disabled="answer.notAnOption" value="{{answer.acode}}">{{answer.name}}</option>
<option style="display:none" value="NONE">NONE</option>
</select>
Then in my js file:
$scope.updateDropDownQuestion = function(question, answer) {
reset(question.code)
$scope.formData["SOLE/SELECTED_QUESTION"] = question.code
$scope.formData["SOLE/SELECTED_ANSWER"] = answer
$scope.formData[question.code+"/"+answer] = true
var questions = $scope.product.questions
for(i=0; i <questions.length;i++){
if(questions[i].code == question.code){
questions[i].sel = answer
break;
}
}
$scope.refresh()
};
the $scope.refresh() is where it changes back. This renders the screen.
no matter what I do it seems to render the previous state and not the current state of the drop down. This is because I am repainting the screen after the drop down changes.
It seems as though the when the screen repaints it is taking the original value first.
Any thoughts on how I can get the value to "stick" once set?
Do I need to fire some event afterwards?
From Angular official site:
Note: ngModel compares by reference, not value. This is important when binding to an array of objects. You might find this helpful to set the default values of your drop down. See an example below.
angular.module('demoApp', []).controller('DemoController', function($scope) {
$scope.options = [
{ label: 'one', value: 1 },
{ label: 'two', value: 2 }
];
// Although this object has the same properties as the one in $scope.options,
// Angular considers them different because it compares based on reference
$scope.incorrectlySelected = { label: 'two', value: 2 };
// Here we are referencing the same object, so Angular inits the select box correctly
$scope.correctlySelected = $scope.options[1];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="demoApp">
<div ng-controller="DemoController">
<div>
<h2>Incorrect</h2>
<p>We might expect the select box to be initialized to "two," but it isn't because these are two different objects.</p>
<select ng-model="incorrectlySelected"
ng-options="opt as opt.label for opt in options">
</select>
The value selected is {{ incorrectlySelected.value }}.
</div>
<div>
<h2>Correct</h2>
<p>Here we are referencing the same object in <code>$scope.correctlySelected</code> as in <code>$scope.options</code>, so the select box is initialized correctly.</p>
<select ng-model="correctlySelected"
ng-options="opt as opt.label for opt in options">
</select>
The value selected is {{ correctlySelected.value }}.
</div>
</div>
</body>
Try using ng-options to render option elements.
Something along these lines:
<select class="form-control"
ng-model="question.sel"
ng-change="updateDropDownQuestion(question,question.sel)"
ng-options="answer.acode as answer.name in question.answers">
</select>
It also depends on what updateDropDownQuestion is doing, can you provide that?
use ng-repeat but can't get option value!
plz help!
html:
<ul ng-controller="app">
<li ng-repeat="mainlist in mainlists">
<p>{{mainlist.name}}</p>
<select ng-options="mainlist.list for mainlist.list in mainlists.list">
<option value="">{{mainlist.list.name}}</option>
</select>
</li>
</ul>
this demo
js: just get {{mainlists.name}} not get {{mainlists.list.name}}
function app($scope) {
$scope.mainlists = [
{
"name":"main001",
"list":[
{
"no":"1",
"name":"sub1"
},{
"no":"2",
"name":"sub2"
}]
},
{
"name":"main002",
"list":[
{
"no":"2-1",
"name":"sub1"
},{
"no":"2-2",
"name":"sub2"
}]
}]
};
this demo
ngOptions directive requires a ngModel directive to be defined on select element.
This is not a documented pitfall, but it is visible from the source code
So, your selects will work if you add ngModel to them:
<select
ng-model="mainlist.value"
ng-options="item as item.name for item in mainlists.list"
>
</select>
Or, if you were not planning to wire up the selects with a model (very unusual case), than you might want to use ng-repeat with your select options:
<select>
<option ng-repeat="item in mainlist.list">{{item.name}}</option>
</select>