I'm working on a filter expression that filters by the data-ID of an element.
The problem I'm having is that the filter will return multiple values if other ID's have the same digits positioned elsewhere (i.e. filter 12 RETURNS 12, 123, 1234). I'd like to just return the one element with the exact value of 12.
JS
angular.module('app', []).controller('TestCtrl', function($scope) {
$scope.customers = [
{
id: 12,
name: 'customer 1 - 1'
},
{
id: 123,
name: 'customer 2 - 12'
},
{
id: 1234,
name: 'customer 3 - 12'
}
];
});
HTML
Filter: <input ng-model="filterCustomer" />
<hr/>
<select size="4" ng-options="customer as customer.name for customer in customers | filter:{id: filterCustomer} track by customer.id" ng-model="customerSelection">
</select>
I've also tried adding the following expression to the filter to match digit length... but it's not working as expected
filter:{id:filterFsaisCustomer.toString().length}
Here is a Plunker.
It should be used as strict checking by adding true inside your filter, also you should have convert the value in integer just by making input field to type="number" will parse that to int.
Markup
<input type="number" ng-model="filterCustomer" />
<select size="4"
ng-options="customer as customer.name for customer in customers | filter:{id: filterCustomer}:true track by customer.id"
ng-model="customerSelection">
</select>
Working Plunkr
Edit
To enable filter only after value entered in textbox then it would become conditional base strict checking | filter:{id: filterCustomer}:filterCustomer>0
<select size="4"
ng-options="customer as customer.name for customer in customers | filter:{id: filterCustomer}:filterCustomer>0 track by customer.id"
ng-model="customerSelection">
</select>
Updated Plunkr
Related
In my Angularjs application, i am having code as follows,
HTML:
<div ng-app="test" ng-controller="test">
<div>
<input type="checkbox" ng-model="showvalidrates"> Display only Valid Rates
<br><br>
<select ng-model="selectRate"
ng-options="option.id as option.name for option in data">
</select>
</div>
</div>
JS:
angular.module('test', [])
.controller('test', ['$scope', function ($scope) {
$scope.data = [
{name: 'Rate 1', id: 1, valid: true},
{name: 'Rate 2', id: 2, valid: false},
{name: 'Rate 3', id: 3, valid: true}
];
$scope.selectRate = $scope.data[1].id;
$scope.showvalidrates = true;
}]);
Here i am making ng-options to display the rates, and i am having a checkbox which will be in checked state by default.
In this scenario, i am in the need to filter the ng-options to display only the valid rates for which i am having a property called valid: true or valid: false.
Here if the checkbox is checked which means showvalidrates is true, then only the object with valid: true needs to be displayed in options.. But if the value is selected already, In the working example given below {name: 'Rate 2', id: 2, valid: false} is selected but it has valid: false in this case the selected value needs to be displayed (means Rate 2 only needs to be in selected state). unless user touches the select box, but if he clicks the select box then only valid rates needs to be displayed and he can select any of the valid rates.
And if he uncheck the showvalidrates (false) then all the rates needs to be displayed in ng-options ..
JsFiddle: http://jsfiddle.net/opygzs4a/
As per example given,
showvalidrates = true
Options:
Rate 1
Rate 2 (Selected)
Rate 3
Onclick on the select box only Rate 1 and Rate 3 needs to displayed and user can select any of these two.
Unless any of these two were chosen the Rate 2 alone needs to be in selected state and selectRate should have the value as 2 only.
The valid property was the newly implemented in code to filter the data, so in order to affect the earlier selectRate value in the application, this scenario needs to be implemented.(Even if valid is false let it be selected unless user changes)..
I am very new in AngularJs and this scenario, so please help me how to handle this situation..
If there is any alternative approach for it it would be also welcomed but requirement is the same as like mentioned above.
To achieve expected result , use below option of using filter with checkbox condition
ng-options="option.id as option.name for option in data|filter: !init && showvalidrates?{valid:true}:{}" ng-init="init = true">
On check, showvalidrates is true and based on that set filter as { valid: true } to display options with flag valid -true
On uncheck, showvalidrates is false and based on that set filter as {}
Add ng-init flag to control initial default value
Codepen - https://codepen.io/nagasai/pen/GbrOMm?editors=1010
working code sample
angular.module('test', [])
.controller('test', ['$scope', function ($scope) {
$scope.data = [
{name: 'Rate 1', id: 1, valid: true},
{name: 'Rate 2', id: 2, valid: false},
{name: 'Rate 3', id: 3, valid: true}
];
$scope.selectRate = $scope.data[1].id;
$scope.showvalidrates = true;
}]);
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<div ng-app="test" ng-controller="test">
<div>
<input type="checkbox" ng-model="showvalidrates" ng-change="init = false"> Display only Valid Rates
<br><br>
<select ng-model="selectRate"
ng-options="option.id as option.name for option in data|filter: !init && showvalidrates?{valid:true}:{}" ng-init="init = true" ng-click="init = false">
</select>
</div>
</div>
I have a dropdown with some values :
Apple
Mango
Orange
Grapes
HTML :
<div class="form-group">
<label class="control-label col-sm-20" for="groupz">Role*</label>
<select class="form-control" ng-model="model.selectedRole" name="role" ng-change="GetRole(model.selectedRole)" >
<option value class selected>Select Roles</option>
<option ng-repeat="item in model.roles track by $index" value="{{item}}">{{item}}</option>
</select>
</div>
I want my $scope.selectedRole to be by default as Apple. But later when the user needs to change the value, they can change it from apple to orange or any other fruit name. I have separate service request to fetch the fruits from backend and I write my code in controller as follows.
$scope.GetRole = function() {
$scope.selectedrole = [];
if ($scope.model.selectedRole != null) {
for (var i = 0; i < 1; i++) {
$scope.selectedrole.push($scope.model.selectedRole);
}
}
}
I hope this helps you
JsFiddle
In js
angular.module('ExampleApp', [])
.controller('ExampleController', function($scope) {
$scope.selectedrole = ['Apple', 'Mango', 'Orange', 'Grapes'];
$scope.selectRole= $scope.selectedrole[0];
});
In HTML
<div ng-app="ExampleApp">
<div ng-controller="ExampleController">
<select ng-model="selectRole" ng-options="role for role in selectedrole">
</select>
</div>
just try : HTML
<select class="form-control select" name="role" id="role" data-ng-model="ctrl.model.selectedRole" data-ng-options="option.name for option in ctrl.model.roles track by option.id"></select>
in your contoller
$scope.model = {
roles: [{
id: '1',
name: 'Apple'
}, {
id: '2',
name: 'Orange'
}, {
id: '3',
name: 'Mango'
}],
selectedRole: {
id: '1',
name: 'Apple'
} //This sets the default value of the select in the ui
};
Then assign the first array element to selectedrole containing the array of values(Apple Mango Orange Grapes).
If you want the default to be apple and the array is ordered:
array = [Apple, Mango, Orange, Grapes]
Your model needs to be set to selectedRole:
data-ng-model="selectedRole"
In your controller, set:
selectedRole = array[0]
angular will take care of the rest of the data manipulation.
I hope this helps. Please provide more information for a clearer answer
Thanks
Handling a select element i.e. a drop down list in AngularJS is pretty simple.
Things you need to know is that you bind it to an array or a collection to generate the set of option tags using the ng-options or the ng-repeat directives which is bound to the data source on your $scope and you have a selected option which you need to retrieve as it is the one the user selects, it can be done using the ng-model directive.
If you want to set the selected option on the page load event, then you have to set the appropriate object or value (here it is the fruit id) which you are retrieving from data binding using the as clause in the ng-options directive as shown in the below embedded code snippet
ng-options="fruit.id as fruit.name for fruit in ctrl.fruits"
or set it to the value of the value attribute when using the ng-repeat directive on the option tag i.e. set data.model to the appropriate option.value
<select size="6" name="ngvalueselect" ng-model="data.model" multiple>
<option ng-repeat="option in data.availableOptions" ng-value="option.value">{{option.name}}</option>
</select>
angular
.module('fruits', [])
.controller('FruitController', FruitController);
function FruitController() {
var vm = this;
var fruitInfo = getFruits();
vm.fruits = fruitInfo.fruits;
vm.selectedFruitId = fruitInfo.selectedFruitId;
vm.onFruitChanged = onFruitChanged;
function getFruits() {
// get fruits and selectedFruitId from api here
var fruits = [
{ id: 1, name: 'Apple' },
{ id: 2, name: 'Mango' },
{ id: 3, name: 'Banana' },
{ id: 4, name: 'Orange' }
];
var fruitInfo = {
fruits: fruits,
selectedFruitId: 1
};
return fruitInfo;
}
function onFruitChanged(fruitId) {
// do something when fruit changes
console.log(fruitId);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="fruits">
<div ng-controller="FruitController as ctrl">
<select ng-options="fruit.id as fruit.name for fruit in ctrl.fruits"
ng-model="ctrl.selectedFruitId"
ng-change="ctrl.onFruitChanged(ctrl.selectedFruitId)">
<option value="">Select Fruit</option>
</select>
</div>
</div>
Check the Example section here for more information.
Im using ngOptions for select directive like
<select class="form-control" ng-model="users.jobTitle" name="jobTitle" data-ng-options="job as job.value for job in ds.jobTitle" required>
im setting default in controller like
$scope.users.jobTitle = $scope.ds.jobTitle[0];
ds is a json with array jobtitle:
"jobTitle":[
{"id":1,"value":"Service1"},
{"id":2,"value":"Service2"},
{"id":3,"value":"Service3"}
],
now i'm saving and getting result(console) like
jobTitle:Object
$$hashKey:"object:173"
id:1
value:"Service1"
now when i'm editing, feeding the service call data like
$scope.useredit.jobTitle = data.jobTitle;
for
<select class="form-control input-sm" ng-model="useredit.jobTitle" name="jobTitle" data-ng-options="job as job.value for job in ds.jobTitle" required>
</select>
its not setting the object as selected , instead sets the null value in first option..
what i have to do ?
By default, ngModel watches the model by reference, not value. This is
important to know when binding the select to a model that is an object
or a collection.
One issue occurs if you want to preselect an option. For example, if
you set the model to an object that is equal to an object in your
collection, ngOptions won't be able to set the selection, because the
objects are not identical. So by default, you should always reference
the item in your collection for preselections, e.g.: $scope.selected =
$scope.collection[3].
Another solution is to use a track by clause, because then ngOptions
will track the identity of the item not by reference, but by the
result of the track by expression. For example, if your collection
items have an id property, you would track by item.id.
~ Taken from the official docs regarding ngOptions
I tested it out by using ng-options in separate select boxes and it works.
See demo below.
angular.module('app', [])
.controller('TestController', ['$scope',
function($scope) {
$scope.ds = {};
$scope.ds.jobTitle = [{
"id": 1,
"value": "Service1"
}, {
"id": 2,
"value": "Service2"
}, {
"id": 3,
"value": "Service3"
}];
var data = {
jobTitle: {
"id": 1,
"value": "Service1"
}
};
$scope.useredit = {
jobTitle: data.jobTitle
};
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="TestController">
<br />Without using track by in ngOptions
<select class="form-control" ng-model="useredit.jobTitle" name="jobTitle" data-ng-options="job as job.value for job in ds.jobTitle" required>
</select>
<br />
<br />
<br />Using track by in ngOptions
<select class="form-control" ng-model="useredit.jobTitle" name="jobTitle" data-ng-options="job as job.value for job in ds.jobTitle track by job.id" required>
</select>
</div>
</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'm trying to achieve a cascade dropdown in Angular. I thought it would just work naturally thanks to binding. See below:
<select name="client" ng-model="selectedRequest.client" ng-options="c.name for c in clients track by c.id" required></select>
<select id="department" ng-model="selectedRequest.department" ng-options="d.defaultLabel for d in selectedRequest.client.departments track by d.id"></select>
When the view is loaded, it works, I can see the departments matching those bound to the client. However, whenever the selectedRequest.client changes, the source for the department dropdown should change too, but instead it becomes empty.
EDIT
I've changed the child dropdown to :
<select id="department" ng-model="selectedRequest.department" ng-options="d.defaultLabel for d in departments track by d.id | filter:{clientId: selectedRequest.client.id}"></select>
but this time it loads all the departments in the dropdown, ignoring the filter.
** EDIT 2 **
Changing to :
<select name="client" ng-model="requestService.selectedRequest.client" ng-options="c as c.name for c in clients track by c.id" required></select>
<select id="department" ng-model="requestService.selectedRequest.department" ng-options="d.defaultLabel for d in departments | filter:{clientId: requestService.selectedRequest.client.id}"></select>
Now the source changes correctly when a client is selected. However the initial selection, i.e setting the right department at startup, does not work. That's because I've removed the 'track by id' bit.
the correct way was
<select id="department" ng-model="selectedRequest.department" ng-options="d.defaultLabel for d in departments | filter:{clientId: selectedRequest.client.id} track by d.id "></select>
it's just that I hadn't put the filter at the right place... silly mistake.
It could be that your selectedRequest.client does not refer to the same object in clients array. Try this:
JS:
function testController($scope) {
$scope.clients = [
{ id: 1, name: "client1", departments: [{ id: 1, defaultLabel: 'department1' }, { id: 2, defaultLabel: 'department2'}] },
{ id: 2, name: "client2", departments: [{ id: 3, defaultLabel: 'department3' }, { id: 4, defaultLabel: 'department4'}] }
];
$scope.selectedRequest = {};
$scope.selectedRequest.client = $scope.clients[0];//Assign by object reference.
}
HTML:
<div ng-controller="testController">
<select name="client" ng-model="selectedRequest.client" ng-options="c.name for c in clients" required></select>
<select id="department" ng-model="selectedRequest.department" ng-options="d.defaultLabel for d in selectedRequest.client.departments"></select>
</div>
DEMO
I removed track by to use the default (track by object reference) and ensure that selectedRequest.client refers to objects inside clients