I am currently using ui-select (https://github.com/angular-ui/ui-select) for dropdowns. I have included select.js and select.css in my index.html file. I have also installed angular-sanitize through bower.
This is what my controller looks like :
use strict';
angular.module('myApp.home', [ 'ui.select', 'ngSanitize']).controller('ScheduleCtrl', ScheduleCtrl);
ScheduleCtrl['$inject'] = [ '$stateParams', '$state' ];
function ScheduleCtrl($stateParams, $state) {
var vm=this;
vm.itemArray = [
{id: 1, name: 'first'},
{id: 2, name: 'second'},
{id: 3, name: 'third'},
{id: 4, name: 'fourth'},
{id: 5, name: 'fifth'},
];
vm.scheduleEvents = [{
id:1,
name:'Event1'
},
{
id:2,
name:'Event2'
}];
}
And my view contains :
<ui-select ng-model="selectedItem">
<ui-select-match>
<span ng-bind="$select.selected.name"></span>
</ui-select-match>
<ui-select-choices repeat="item in (vm.itemArray | filter: $select.search) track by item.id">
<span ng-bind="item.name"></span>
</ui-select-choices>
</ui-select>
However, my view is blank and it does not seem to be hitting the ui-select directive.
Remove ( and ).
<ui-select-choices repeat="item in vm.itemArray | filter: $select.search track by item.id">
<span ng-bind="item.name"></span>
</ui-select-choices>
See running on plunker.
Another thing you can test, comment this line:
//ScheduleCtrl['$inject'] = [ '$stateParams', '$state' ];
I didn't understand what it is doing, but with it the example on plunker doesn't work.
Related
I am using ui-select as follows.
<ui-select id="ItemId" ng-model="ctrl.ItemId" theme="bootstrap"
ng-disabled="ctrl.DownDisabled" required>
<ui-select-match placeholder={{ctrl.Placeholder}}>{{$select.selected.item}}
</ui-select-match>
<ui-select-choices
repeat="item in ctrl.owners.components">
<div ng-bind-html="item | highlight: $select.search"></div>
</ui-select-choices>
<ui-select-no-choice>
No features were found
</ui-select-no-choice>
</ui-select>
The JSON it is itearing over is
ctrl.owners = {
value : 123,
teamName : ABC,
components : [a,b,c]
};
But UI dropdown shows "No features were found" . What is the issue. My objective is to show the components as individual choices in the drop-down. AFAIK this needs to be done in some way by using a nested repeat in ui-select-choices . How canI do that?
<div class="form-group ">
<ui-select ng-model="person.selected" theme="bootstrap">
<ui-select-match placeholder="Select or search a person in the list...">{{$select.selected.name}}</ui-select-match>
<ui-select-choices repeat="item in people | filter: $select.search">
<div ng-bind-html="trustAsHtml((item.name | highlight: $select.search))"></div>
<small ng-bind-html="trustAsHtml((item.email | highlight: $select.search))"></small>
</ui-select-choices>
</ui-select>
</div>
$scope.people = [
{ name: 'Adam', email: 'adam#email.com', age: 12, country: 'United States' },
{ name: 'Amalie', email: 'amalie#email.com', age: 12, country: 'Argentina' }];
You can use like this it will work.
Here trustAsHtml is method.
$scope.trustAsHtml = function(value) {
return $sce.trustAsHtml(value);
};
I have an angular app and using ui-select, on the page there two input fields with multiselectors, both of them dropdown lists. Everything works fine. When I choose an option in first field (in this case its programming language) the second field (frameworks that belongs to particular programming language) must be filtrated and show only list of correct frameworks.
WORKING CODE:
<div class="col-md-2 col-md-offset-2">
<ui-select multiple ng-model="newdeveloper.langs">
<ui-select-match placeholder="Select skills">[[ $item.lang_name ]]</ui-select-match>
<ui-select-choices repeat="item in (allSkillList.langs | filter: $select.search) track by item.id">
<span ng-bind="item.lang_name"></span>
</ui-select-choices>
</ui-select>
</div>
<div class="col-md-2">
<ui-select multiple ng-model="newdeveloper.frameworks">
<ui-select-match placeholder="Select frame">[[ $item.frame_name ]]</ui-select-match>
<ui-select-choices repeat="item in (allSkillList.frameworks | filter: $select.search) track by item.id">
<span ng-bind="item.frame_name"></span>
</ui-select-choices>
</ui-select>
</div>
JSON WITH DATA:
{
"frameworks": [
{
"id": 1,
"frame_name": "Django",
"frame_lang": 1
},
{
"id": 2,
"frame_name": "jQuery",
"frame_lang": 2
},
{
"id": 3,
"frame_name": "Spring",
"frame_lang": 3
}
],
"langs": [
{
"id": 1,
"lang_name": "Python"
},
{
"id": 2,
"lang_name": "JavaScript"
},
{
"id": 3,
"lang_name": "Java"
},
]
}
"frameworks.frame_lang" must match with "langs.id" in order to make filter work properly.
THE QUESTIONS:
How can I resolve this problem? Should I use some custom filter?
Thank you!
You have to create a custom filter filterByLang and then apply it to frameworks repeat.
angular.module('demoApp').filter('filterByLang',function(){
return function(frameworks,langs){
var filtered = [];
if(langs && langs.length){
angular.forEach(frameworks,function(framework){
angular.forEach(langs,function(lang){
if(framework.frame_lang == lang){
filtered.push(framework);
}
})
});
}
return filtered;
};
});
Inside html update your second dropdown code by.
...
<ui-select-choices repeat="item in (allSkillList.frameworks | filterByLang: newdeveloper.langs | filter: $select.search) track by item.id">
...
So I have a pretty basic select that looks like this:
<ui-select theme="select2" search-enabled="false" ng-model="obj.myModel">
<ui-select-match>{{$select.selected.name}}</ui-select-match>
<ui-select-choices repeat="item.value as item in choices">
<span>
{{item.name}}
</span>
</ui-select-choices>
</ui-select>
Let's say the choices are defined as
$scope.choices = [
{value: 'some_value_1', name: 'Default name'},
{value: 'some_value_2', name: 'Default name 2'}
]
Now let's assume that the user has selected the item with value some_value_1. After that a server response comes in that updates the choices list with different names
$scope.choices = [
{value: 'some_value_1', name: 'Real name'},
{value: 'some_value_2', name: 'Real name 2'}
]
Notice that the value part that is saved in the model stays the same. The name in <ui-select> is still Default name when I would want it to change to Real name.
plnkr.co
Is there a way to make the selected name correspond to updated choices?
I have hierarchical data set. There is one fixed root unit.
What I want to do is to make this tree browsable with dependent selects.
I have created a simple plunkr example with a fixed dataset.
http://plnkr.co/edit/Bz5A1cbDLmcjoHbs5PID?p=preview
The data format in the example mimics the format I would get from a server request in "real" life.
This working fine in this simple first step. What is missing is, that when a user changes a selection somewhere in the middle, the select boxes and the ng-model binding below the new selection need to be destroyed.
So when I select Europe->France->Quimper and change "Europe" to "Asia" - then there should be "Asia" as the first select box and a second one the Asia countries.
Is there an "Angular" way to deal to deal with this? Any other hint is appreciated also ;)
<!DOCTYPE html>
<html ng-app="app">
<head>
<link data-require="bootstrap#3.3.5" data-semver="3.3.5" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" />
<script src="https://code.angularjs.org/1.3.17/angular.js" data-semver="1.3.17" data-require="angular.js#1.3.17"></script>
</head>
<body>
<div ng-controller="Ctrl">
<select ng-repeat="select in selects track by $index" ng-model="$parent.boxes[$index]">
<option ng-repeat="child in select.children" ng-click="expandSelects(child)">{{child.name}}</option>
</select>
<ul>
<li ng-repeat="item in boxes">{{ item }}</li>
</ul>
</div>
<script>
var app = angular.module('app', []);
app.controller('Ctrl', ['$scope', function($scope) {
var data = {
'europe': {
name: 'europe',
children: [{
name: 'france',
parent: 'europe'
}, {
name: 'italy',
parent: 'europe'
}],
},
'asia': {
name: 'asia',
children: [{
name: 'japan',
parent: 'asia'
}, {
name: 'china',
parent: 'asia'
}],
},
'france': {
name: 'france',
children: [{
name: 'paris',
parent: 'france'
}, {
name: 'quimper',
parent: 'france'
}]
}
};
var root = {
name: 'world',
children: [{
name: 'europe',
parent: 'world'
}, {
name: 'asia',
parent: 'world'
}, ]
};
$scope.selects = [root];
$scope.expandSelects = function(item) {
var select = data[item.name];
if (select) {
$scope.selects.push(select);
}
}
$scope.$watch('boxes', function(item, old) {
}, true);
}]);
</script>
</body>
</html>
This is a classic example of cascading dropdowns, with the added challenge of an unknown number of levels in the cascade. I combined the data set into one object for simplicity, added labels for the dropdowns, and simplified the select element.
This solution allows for any number of levels, so if you needed data below the city level, you could add it without changing any code, as illustrated by the "Street" example I added to Paris.
select {
display: block;
}
<!DOCTYPE html>
<html ng-app="app">
<head>
<link data-require="bootstrap#3.3.5" data-semver="3.3.5" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" />
<script src="https://code.angularjs.org/1.3.17/angular.js" data-semver="1.3.17" data-require="angular.js#1.3.17"></script>
</head>
<body>
<div ng-controller="Ctrl">
<div ng-repeat="select in selects track by $index" ng-if="select.children">
<label>{{ select.optionType }}</label>
<select ng-model="selects[$index + 1]" ng-options="child.name for child in select.children" ng-change="clearChildren($index)"></select>
<hr />
</div>
</div>
<script>
var app = angular.module('app', []);
app.controller('Ctrl', ['$scope', function($scope) {
var data = {
optionType: 'Continent',
name: 'World',
children: [
{
optionType: 'Country',
name: 'Europe',
children: [
{
optionType: 'City',
name: 'France',
children: [
{
optionType: 'Street',
name: 'Paris',
children: [
{
name: 'First'
},
{
name: 'Second'
}
]
},
{
name: 'Quimper'
}
]
},
{
name: 'Italy'
}
]
},
{
optionType: 'Country',
name: 'Asia',
children: [
{
name: 'Japan'
},
{
name: 'China'
}
]
}
]
};
$scope.selects = [data]
$scope.clearChildren = function (index) {
$scope.selects.length = index + 2;
};
}]);
</script>
</body>
</html>
To go to the children in your hierachy is not as hard as it may seem. If you set up your select with angular and let it do most of the selection for you (for example using ng-options instead of ng-repeating the tag itself), and tell it what options there are, then the list of children you are trying to render just becomes a standard ng-repeat of the children that were picked from the select above.
I modified your plunker to show you how you could accomplish that a slightly different way.
http://plnkr.co/edit/zByFaVKWqAqlR9ulxEBt?p=preview
Main points I changed were
$scope.expandSelects = function() {
var select = data[$scope.selected.name];
if (select) {
console.log('changed');
console.log(select);
$scope.chosen = select;
}
}
Here i just grab the chosen item which the will use. Then the ends up looking like.
<ul>
<li ng-repeat="item in chosen.children">{{ item.name }}</li>
</ul>
The only other set up that was really needed was setting up the with ng-options and giving it a model to bind to.
<select ng-options="child.name for child in selects.children"
ng-model="selected" ng-change="expandSelects()">
</select>
Use can use a filter on the second select to filter de options based on the previous selection.
For example, you can have a first selection to choose the continent:
<select ng-options="c for c in continents" ng-model="selectedContinent" ></select>
and a second selection for the coutries:
<select ng-options="c.name for c in countries | filter : {parent:selectedContinent}" ng-model="selectedCountry" ></select>
Made a fiddle with a simplified data structured just to show how the filter works: http://jsfiddle.net/marcosspn/oarL4n78/
I'm trying to perform an orderBy operation in AngularJS based on a chosen select box value.
The problem I'm having is changing the optional :true or :false flags depending on the selected value.
For example, 'alphabetical' order, the flag would have to be :false, but for 'date' (most recent), the flag needs to be :true.
I've tried hardcoding the flags in the scope options but still not working.
html
<div>
<label>Country filter</label>
<input type="text" ng-model="countryFilter" />
<label>Order by</label>
<select ng-model="selectedOrder" ng-options="option for option in options"></select>
</div>
<ul>
<li ng-repeat="detail in details | filter:{country: countryFilter} | orderBy:selectedOrder">{{ detail }}</li>
</ul>
app.js
var app = angular.module('plunker', []);
app.controller('MyCtrl', function($scope) {
// order by options
$scope.options = ['country', 'address', 'date'];
// all countries
$scope.details = [{
id:1, country:'Finland', address:'Mainstreet 2', date:'2015-05-02'
},{
id:2, country:'Mexico', address:'Some address', date:'2015-05-05'
},{
id:3, country:'Canada', address:'Snowroad 45', date:'2015-03-02'
}];
});
Here is a plunker.
I would suggest to change your order options from strings to objects, which include the information if the list should be reversed for this order:
$scope.options = [{value : 'country', reversed : false}, {value : 'address', reversed : false}, {value : 'date', reversed : true}];
And the ng-repeat to:
<li ng-repeat="detail in details | filter:{country: countryFilter} | orderBy:selectedOrder.value:selectedOrder.reversed">{{ detail }}</li>
http://plnkr.co/edit/JXtHa2jXUy7Y5BsvsdL9?p=preview