When I try to display my value the select box is always empty. The value is a integer 0 1 2 3 . In this case it should show 0, but the box is empty. What am I doing wrong?
vmDialog.dataModel.requestType value is equal to a 0 integer, but not displaying.
<select class="form-control " name="requestType" ng-model="vmDialog.dataModel.requestType">
<option value=0>0</option>
<option value="{{0}}">0</option>
<option value="0">0</option>
</select>
Firstly there is a simple HTML issue, you need to ensure that each option has a unique value, so far you have used the value 0 for all the options, so when the requestType has a value of 0, the UI cannot pick which of the items should be selected.
If the value supposed to be one of 0,1,2,3 then you need to make sure that there is an option with a corresponding value that can be selected.
What you probably want to do is bind the options to an array that is in the view model:
// on vmDialog
var requestTypeOptions = [
{ name = 'Zero', value = 0 },
{ name = 'One', value = 1 },
{ name = 'Two', value = 2 },
{ name = 'Three', value = 3 },
];
Then in the view: (using ng-options)
<select class="form-control"
name="requestType"
ng-model="vmDialog.dataModel.requestType"
ng-options="o.value as o.name for o in vmDialog.requestTypeOptions track by o.value | orderby: 'value'"
class="form-control input-sm">
</select>
A good write-up for ng-options here: https://stackoverflow.com/a/30507651/1690217
You could also use ng-repeat if you need to customise the template:
<select class="form-control " name="requestType" ng-model="vmDialog.dataModel.requestType">
<md-option ng-value="o.value" ng-repeat="oin vmDialog.requestTypeOptions | orderBy: 'value'">{{o.name}}</md-option>
</select>
Related
I have two selects
The first one is for regions
and the second one for cities
The first one is filled with regions
Now i have a methode that brings cities by the id of the region .
I dont know how to get the idregion and put it into the params function
This is my first select
<div class="form-group">
<label for="">Region</label>
<select class="form-control"
[(ngModel)]="region" name="Region">
<option></option>
<option *ngFor="let region of
objectKeys(dropDownList2)|keys"
[value]="dropDownList2[region].idRegion">
{{dropDownList2[region].nomRegion}}
</option>
</select>
</div>
My services :
getville() {
return this.http.get(this.urltest + 'Villes');
}
getRegion() {
return this.http.get(this.urltest + 'Regions');
}
GetRegionVille(idRegion) {
return this.http.get(this.urltest + 'Villes/GetRegionVille/' + idRegion);
}
My component.ts :
getidregion() {
this.res.getRegion().subscribe(R => {
this.dropDownList2 = R as any;
});
}
getregionville() {
this.res.GetRegionVille(****i don t know how to get the idregion**** )
.subscribe(response => {
this.dropDownList = response as any;
});
}
this is my function
// GET: api/Villes
[HttpGet("GetRegionVille/{id}")]
public async Task<IActionResult> GetRegionVille([FromRoute] int id)
{
var req = from v in _context.Villes
join r in _context.Regions
on v.IdRegion equals r.IdRegion
where r.IdRegion == id
select new {v.NomVille };
return Ok(req);
}
My select of the cities :
<div class="form-group">
<label for="">Ville</label>
<select class="form-control" name="Ville"
[(ngModel)]="ville">
<option></option>
<option *ngFor="let ville of objectKeys(dropDownList) |
keys"
[value]="dropDownList[ville].idVille">
{{dropDownList[ville].nomVille}}
</option>
</select>
The selected value will be in region variable as you state [(ngModel)]="region" and you can use (ngModelChange)="onChange($event)" to get an event when value changes
I am not sure if using two way data binding with (ngModelChange) is efficient, so please see this answer How can I get new selection in "select" in Angular 2?
I wanted to default the first value of a json array object to a drop down list
<select ng-model="selectedItem" ng-options="item as item.taskName for item in abc.taskList" ng-init="selectedItem = selectedItem || abc.taskList[0].taskName">
<pre>{{selectedItem | json}}</pre>
</select>
I have tried ng-init and setDefault, but nothing worked. Every time a blank option values comes first then comes the taskList values.
this is how my array looks like
$rootScope.abc = {
taskList: [{
'projectId': '',
'taskId': '',
'taskName': ''
}]
};
Here is the json array Object
{
"returnCode": "0",
"returnMsg": "Success",
"taskList": [{
"taskId": "123",
"taskName": "TimeSheet"
}, {
"taskId": "345",
"taskName": "Travel Expense"
},{
"taskId": "653",
"taskName": "Attendance"
}]
}]
}
How do I default TimeSheet as the default value in the dropdown list?
Option 1
Set: ng-options="item.taskName as item.taskName for item in abc.taskList"
<select ng-model="selectedItem"
ng-options="item.taskName as item.taskName for item in abc.taskList"
ng-init="selectedItem = selectedItem || abc.taskList[0].taskName" >
</select>
Demo 1
In ng-init you use abc.taskList[0].taskName a.e. taskName therefore to make it work we need ot use model as item.taskName as item.taskName
Option 2
Set selectedItem as abc.taskList[0]
<select ng-model="selectedItem"
ng-options="item as item.taskName for item in abc.taskList"
ng-init="selectedItem = abc.taskList[0]">
</select>
Demo 2
Using this ng-selected="$first" you will get first value as selected in dropdown.
Set first value Your scope List in controller Like that
$scope._yourscope.projectId= ($scope.taskList.length > 0) ? $scope.taskList[0].projectId: '';
Here is my runable Plunker
I want to sort items by name. This is the bug, for the top one, "Please select a student name", it displays as an empty field.
<select ng-options="student as student.name for student in students | orderBy: sortNameExcludeTopOne"
ng-model = "student">
</select>
$scope.sortNameExcludeTopOne = function(student) {
if (student.id === 0) {
return -1;
}
return student.name;
}
What I want:
Now I sort items by its name by using a custom function in the controller, can we do sort items by its name in the template? instead of in controller?
What UI I want for select is:
"Please select a student name" -> "Bar" -> "Foo"
Update: I want the "Please select a student name" at the top of select
You don't need push the item to array, you can put then direct in the view:
<select ng-options="student as student.name for student in students | orderBy: 'name'" ng-model = "student">
<option value="">Please select a student name</option>
</select>
You want the options available to them sorted by the name:
<select ng-options="student as student.name for student in students | orderBy: 'name'" ng-model="student">
</select>
That should sort the students by their 'name' property.
Edit:
If you want to add the extra option at the top, then, use your controller to sort the 'students' first:
students() {
const studentList = someStudents();
studentList.sort((a, b) => {
if(a.name < b.name) return -1;
if(a.name > b.name) return 1;
return 0;
});
studentList.unshift({ new: option, goes: here });
}
Then you can sort it there, and insert one more option at the beginning with the option you want visible.
Incidentally you could use orderBy: 'name' still, assuming your options are based on 'value'; you'd have to have one more default entry with a numeric value like so:
<select ng-options="student as student.name for student in students | orderBy: 'name'"
ng-model="student">
<option value="-1">Please select a student name:</option>
</select>
I'm trying to filter one drop down list (DDL) based on a selection made in another. I was referencing this question for how to do it: Angularjs Filter data with dropdown
My DDLs look like this:
<select class="form-control input-sm"
ng-change="echo(selectedDepartment);"
ng-model="selectedDepartment"
ng-options="d as d.DepartmentName for d in departmentList track by d.DepartmentId"></select>
<select class="form-control input-sm"
ng-change="echo(selectedTeam);"
ng-model="selectedTeam"
ng-options="t as t.TeamName for t in (teamList | filter: filterTeams) track by t.TeamId"></select>
<select class="form-control input-sm"
ng-change="echo(selectedRep);"
ng-model="selectedRep"
ng-options="r as (r.FirstName + ' ' + r.LastName) for r in (repList | filter: filterReps) track by r.UserId"></select>
The echo function in ng-change is just using console.log so I can verify that the model is being updated when a selection is made and it is.
Here are my filter functions:
$scope.filterTeams = function (team) {
console.log("Team's DeptId: " + team.Department.DepartmentId + " Selected Dept Id: " + $scope.selectedDepartment.DepartmentId);
return (team.Department.DepartmentId === $scope.selectedDepartment.DepartmentId);
};
$scope.filterReps = function(rep) {
return (rep.TeamId === $scope.selectedTeam.TeamId);
};
What's strange is that when I reference $scope.selectedDepartment in my filter function it's always an empty object even after the echo function running in ng-change shows it's been updated.
The filter functions are part of the same controller that the DDLs are referencing and have the same $scope object.
When I select a department my team DDL goes blank since it's comparing team.Department.DepartmentId to undefined.
How can $scope.selectedDepartment be an empty object and be populated at the same time?
For inexplicable reasons you can't use $scope in a filter function. So to make this work you have to create a local variable in your controller and copy the value from your $scope variable to the local one for the filter function to use. Then everything works.
Here's the updated view:
<select class="form-control input-sm"
ng-change="updateSelectedDepartment(selectedDepartment);"
ng-model="selectedDepartment"
ng-options="d as d.DepartmentName for d in departmentList track by d.DepartmentId"></select>
<select class="form-control input-sm"
ng-change="updateSelectedTeam(selectedTeam);"
ng-model="selectedTeam"
ng-options="t as t.TeamName for t in (teamList | filter: filterTeams) track by t.TeamId"></select>
<select class="form-control input-sm"
ng-model="selectedRep"
ng-options="r as (r.FirstName + ' ' + r.LastName) for r in (repList | filter: filterReps) track by r.UserId"></select>
And here's the relevant sections from the controller:
var selectedDepartment = {};
var selectedTeam = {};
$scope.updateSelectedDepartment = function(dept) {
selectedDepartment = dept;
};
$scope.updateSelectedTeam = function (team) {
selectedTeam = team;
};
$scope.filterTeams = function (team) {
return (team.Department.DepartmentId === selectedDepartment.DepartmentId);
};
$scope.filterReps = function (rep) {
return (rep.Team.TeamId === selectedTeam.TeamId);
};
Here's another option...instead of making the filter a function on your controller, make it an actual filter (the added benefit there is you can reuse the filter in other areas). So do this:
.filter('teamsFilter', function() {
return function(teamsList, selectedDepartment) {
var out = [];
angular.forEach(teamsList, function(team) {
if (team.Department.DepartmentId === selectedDepartment.DepartmentId) {
out.push(team);
}
});
return out;
}
})
And then use it like this:
<select ng-model="selectedTeam"
ng-options="t as t.TeamName for t in (teamList | teamsFilter: selectedDepartment)"></select>
I've a got a strange issue. When I try to select a date the select() function selects the wrong option.
Ng-Model:
days = ['01', '02', '03', '04', ..., '31'];
Markup:
<select ng-model="day" id="day" name="day" ng-options="day for day in days">
<option value="" disabled="disabled"></option>
</select>
e2e test:
it('should select correct date', function () {
select('day').option('30');
expect(element('#day option:selected').text()).toEqual('30');
});
So my question is: Why does select('day').option('30') select the 31th day when select('day').option('02') works as expected?
So I was wondering what value it's targeting as it's working fine in other places.
The documentation is very sparse so either it's a feature or a bug :)
What I think is going on is the select() tries to select the value in some sort of order. I.E. it first tries to select the option by value then it tries to select it by model value, or something along those lines.
So I looked up the implementation of the select function.
From github:
/**
* Usage:
* select(name).option('value') select one option
* select(name).options('value1', 'value2', ...) select options from a multi select
*/
angular.scenario.dsl('select', function() {
var chain = {};
chain.option = function(value) {
return this.addFutureAction("select '" + this.name + "' option '" + value + "'",
function($window, $document, done) {
var select = $document.elements('select[ng\\:model="$1"]', this.name);
var option = select.find('option[value="' + value + '"]');
if (option.length) {
select.val(value);
} else {
option = select.find('option').filter(function(){
return _jQuery(this).text() === value;
});
if (!option.length) {
option = select.find('option:contains("' + value + '")');
}
if (option.length) {
select.val(option.val());
} else {
return done("option '" + value + "' not found");
}
}
select.trigger('change');
done();
});
};
return function(name) {
this.name = name;
return chain;
};
});
So the "problem" is that select tries to select from the values in the DOM element, that is the <option value="THIS VALUE"> then it tries to find the value by what's being displayed <option>THIS VALUE</option> and then it tries to do a contains on the value. It doesn't actually use the model value at any point.
So select('day').option('02') worked because it was matching the displayed text, where as select('day').option('30') was matching the option value which has an offset.
Keep in mind the generated HTML is:
<select ng-model="day" id="day" name="day" ng-options="day for day in days">
<option value="" disabled="disabled"></option>
<option value="0">01</option> <-- note it starts at 0 not 1
<option value="1">02</option> <-- select('day').option('02') matches display text '02' as no value 02 exists.
<option value="2">03</option>
<option value="29">30</option>
<option value="30">31</option> <-- select('day').option('30') matches value 30 before display text 30 with value 29.
</select>
To "solve" this issue a new function needs to be created (or alter the existing).
angular.scenario.dsl('selectModel', function() {
var chain = {};
chain.option = function(value) {
return this.addFutureAction("select '" + this.name + "' option '" + value + "'",
function($window, $document, done) {
var $ = $window.$; // jQuery inside the iframe
var select = $document.elements('select[ng\\:model="$1"]', this.name);
var option = select.find('option').filter(function(){
return $(this).text() === value;
});
if (!option.length) {
option = select.find('option:contains("' + value + '")');
}
if (option.length) {
select.val(option.val());
} else {
return done("option '" + value + "' not found");
}
select.trigger('change');
done();
});
};
return function(name) {
this.name = name;
return chain;
};
});
This does the trick.
The Angular created option tags have indices as value, when the source model is a list:
$scope.listItems = [
"day 1",
"day 2",
"day 3",
"day 4",
"day 5"
];
and
<select ng-model="listItem" ng-options="item for item in listItems"></select>
create the following HTML:
<select ng-options="item for item in listItems" ng-model="listItem"
class="ng-pristine ng-valid">
<option value="?" selected="selected"></option>
<option value="0">day 1</option>
<option value="1">day 2</option>
<option value="2">day 3</option>
<option value="3">day 4</option>
<option value="4">day 5</option>
</select>
While the option tags have keys as value, when the source model is a map:
$scope.objItems = {
"day 1":"1",
"day 2":"2",
"day 3":"3",
"day 4":"4",
"day 5":"5"
};
and
<select ng-model="objItem2" ng-options="value as key for (key, value)
in objItems"></select>
create:
<select ng-options="value as key for (key, value) in objItems"
ng-model="objItem2" class="ng-valid ng-dirty">
<option value="day 1" selected="selected">day 1</option>
<option value="day 2">day 2</option>
<option value="day 3">day 3</option>
<option value="day 4">day 4</option>
<option value="day 5">day 5</option>
</select>
However this never poses a problem because when the user selects an option, Angular looks up at the indexed position inside the source and assigns that value to the model.
I am not quite familiar with e2e testing but I think the reason you are getting a different value everytime you select an option is that you are trying to access the value stored in the option tag and not what Angular has stored in the model for you.
Fiddle