I am working with <ui-select> and came across a problem I apparently do not understand how to tackle. There is a bunch of related topics on it here on SO, however, none of them covered my specific problem, which is I think quite simple for people who have worked with this directive before.
I have a big object with item objects inside, like this one:
let items = [{id: 1, name: 'name'}, {id: 2, name: 'name2'}];
I am iterating over object to make it visible in front. The option will be displayed in
<ui-select-match allow-clear="true">
<span>{{ $select.selected.label }}</span>
</ui-select-match>
The label will be selected in controller based on the "watched" value. My question here is what should I set in ng-model to watch the changes on the level of individual items and update it?
I tried to use track by index, ng-change instead of watch and a bunch of other approaches which brought no results.
Template:
<div ng-repeat="item in vm.items">
<div class="form-group field">
<label>Items:</label>
<ui-select ng-model="item.id"
ng-keyup="vm.newItems({ keyword: $select.search })"
search-enabled="false">
<ui-select-match allow-clear="true">
<span>{{ $select.selected.label }}</span>
</ui-select-match>
<ui-select-choices repeat="item.id as item in vm.shortlistsList">
<pre>Name: {{ item.label }}</pre><pre>Id: {{ item.id }} </pre>
</ui-select-choices>
</ui-select>
</div>
In controller:
function $onChanges() {
$scope.$watch('item.id', function (newValue, oldValue) {
console.log(item.id);
});
}
QUESTION: How can I watch each individual item, what/how should I pass to ng-model? At the moment I see no way of doing it as my half day of attempts is gone in vain.
Following a long and painful day of experiments, I found a workable solution:
Template:
<div ng-repeat="item in vm.items track by $index">
<div class="form-group field">
<label>Items:</label>
<ui-select ng-model="item[$index]"
ng-keyup="vm.newItems({ keyword: $select.search })"
search-enabled="false">
<ui-select-match allow-clear="true">
<span>{{ $select.selected.label }}</span>
</ui-select-match>
<ui-select-choices repeat="item.id as item in vm.shortlistsList">
<pre>Name: {{ item.label }}</pre><pre>Id: {{ item.id }} </pre>
</ui-select-choices>
</ui-select>
</div>
Controller:
for (let i = 0; i < vm.items.length; i++) {
$scope.$watch('vm.items[' + i + ']', function (newValue, oldValue) {
if (newValue && oldValue !== null) {
return newValue.label = newValue.name;
}
}, true);
}
Related
I wanted to pass everytime i select an item from a ui-select to the controller I did try to use ng-update and ng change but it does not seem to work. Any idea? why code is below. Thank you. I just want to trigger a function once i select an item from the ui select.
controller
$scope.update = function () {
alert("triggered")
}
view
<ui-select ng-change="update()" multiple="multiple" tagging="tagging" tagging-label="(custom 'new' label)" ng-model="main.record.skills" theme="bootstrap" sortable="true" style="width: 300px;" title="">
<ui-select-match class="ui-select-match" placeholder="Select skills">{$ $select.selected.name $}{$ $item.name | limitTo:70 $} {$ $item.name.length > 70 ? "..." : "" $}</ui-select-match >
<ui-select-choices ng-change="main.update()" refresh="main.read_skills($select.search)" repeat="skill in main.skills | filter:$select.search track by $index">
<div ng-bind-html="skill.name | highlight: $select.search"></div>
{$ name $}
</ui-select-choices>
</ui-select>
Add on-select="onSelected($item)" to your ui-select and in controller:
$scope.onSelected = function (selectedItem) {
//do selectedItem.PropertyName like
//selectedItem.Name or selectedItem.Key
//whatever property your list has.
}
As I mentioned in topic i try do depends checkboxes from dropdownlist. I fill data to my dropdownlist from controller:
#RequestMapping(value = "/all", method = GET)
public List<Warehouse> findAll(){
return warehouseService.findAll();
}
$http
.get('/api/warehouses/all')
.then(function (response) {
$scope.warehouses = response.data;
});
Every Warehouse object have a List with package:
#OneToMany
private List<Package> packages = new ArrayList<>();
Now when i am creating Route and when i select one Warehouse from dropdownlist i wanna fill checkboxes from List from currently selected Warehouse.
Select Warehouse:
<select ng-model="credentials.warehouseStart">
<option ng-selected="credentials.warehouseStart == x" id="startId" ng-value="x" ng-repeat="x in warehouse" >{{x.name}}</option>
</select>
And checkboxes:
<div flex-xs flex="50">
<md-checkbox aria-label="Select All"
ng-checked="isChecked()"
md-indeterminate="isIndeterminate()"
ng-click="toggleAll()">
<span ng-if="isChecked()">Un-</span>Select All
</md-checkbox>
</div>
<div class="demo-select-all-checkboxes" ng-model="credentials.packages" flex="100" ng-repeat="item in packages">
<md-checkbox ng-checked="exists(item, selected)" ng-click="toggle(item, selected)">
{{ item.name }} <p> </p>
{{ item.user.firstName }} {{ item.user.lastName }}
</md-checkbox>
</div>
Checkbox fill:
$http
.get('/api/package/all')
.then(function (response) {
$scope.packages = response.data;
});
It is possible if i select one object in Dropdowlist(Warehouse) can i get a object id? Then i think i can get a correct chebkoxes by directive /package/all/{id} ?
I am basing my answer of your comment that every warehouse has a list of packages. That said, I am expecting packages to be a part of your GET call to /api/warehouses/all.
First, I would change your warehouse selection to use ngOptions:
<select ng-model="selected.warehouse"
ng-options="x.name for x in warehouses"></select>
Then, to list the packages:
<div ng-model="selected.packages"
ng-repeat="item in selected.warehouse.packages">
<input type="checkbox"
ng-checked="exists(item, selected)"
ng-click="toggle(item, selected)"> {{ item.name }}
<p> </p>
{{ item.firstName }} {{ item.user.lastName }}
</div>
I have created a sample here. Within, I have added a couple of wrappers around the package list in your ui using ngIf, but that's not necessary, but figured you'd probably have a view area to show based on whether or not a selection was made.
I'm unable to access the selected dropdown value in UI-Select, How do I access the selected values in the controller?
<ui-select name="optionType" ng-model="optionType.selected" theme="bootstrap" append-to-body="true" reset-search-input="true">
<ui-select-match placeholder="Option">
<span ng-bind-html="ctrl.trustAsHtml($select.selected.type)"></span>
</ui-select-match>
<ui-select-choices repeat="option in optionTypes | filter: $select.search" position="down">
<span ng-bind-html="ctrl.trustAsHtml(option.type) | highlight: $select.search"></span>
</ui-select-choices>
</ui-select>
Controller:
$scope.optionType = {};
$scope.optionTypes =
[
{type: "Risk Reversal"},
{type: "Straddle"},
{type: "Strangle"},
{type: "Spread"},
{type: "VANILLA"}
]
Check their 'Object as source' example
You need to bind it to repeat like this:
<ui-select-choices repeat="item.type as item in optionTypes">
There I don't see a need of using ng-bind-html by looking at your dropwon collection. Although if you need it there make sure you have trustAsHtml function, inside your controller $scope and then use trustAsHtml(selected.type) instead of ctrl.trustAsHtml(selected.type).
Without ng-bind-html
<ui-select name="optionType" ng-model="optionType.selected" theme="bootstrap" append-to-body="true" reset-search-input="true">
<ui-select-match placeholder="Option">
<span ng-bind="$select.selected.type"></span>
</ui-select-match>
<ui-select-choices repeat="option in optionTypes | filter: $select.search" position="down">
<span ng-bind="option.type | highlight: $select.search"></span>
</ui-select-choices>
</ui-select>
Demo Here
In my template i have :
<div ng-if="$ctrl.show()">
<input class="form-control" type="text">
</div>
In my component
show() {
if (angular.isDefined(this.parking.parkingType)) {
return this.parking.parkingType.labelKey === 'parking_type.air'
}
}
I want angular to process the function only when clicking on a select input (ui-select) by the attribute on-select="$ctrl.show()" :
<ui-select ng-model="$ctrl.parking.parkingType"
on-select="$ctrl.show()">
<ui-select-match allow-clear="true">
<span>{{ $select.selected.label }}</span>
</ui-select-match>
<ui-select-choices repeat="item in $ctrl.parkingType | filter: { label: $select.search }">
<span ng-bind-html="item.label"></span>
</ui-select-choices>
</ui-select>
This case may be similar to a sample case of: launching the function only when clicking on an ng-click
change your ng-show to a variable and keep on-select="$ctrl.show()" as is
In your view:
<div ng-if="$ctrl.shouldShow">
<input class="form-control" type="text">
</div>
In your component:
$ctrl.show = function() {
if (angular.isDefined(this.parking.parkingType)) {
$ctrl.shouldShow = (this.parking.parkingType.labelKey === 'parking_type.air')
}
}
It's a good practice not to have a function in ng-if, ng-show, and ng-hide because it's a performance hit
I have an HTML for select tag, with this code :
<div ng-controller="Models">
<select ng-model="myModel" ng-options="Model.name for Model in Models" class="form-control"></select>
{{ {selected_Model:myModel.name} }} {{ {selected_Model:myModel.id} }}
</div>
and I want it to show only myModel.id==1.
how can I do it ?
I think this question needs a bit more of an explanation.
Do you mean you want to display a select for each model in models however only if the model.id ==1?
You can do this with a filter, while the models are being written to the page in your select box this filter checks if they have an .id == 1 and if TRUE then allows it to be written into the select.
I would imagine however that this means you'll only have 1 item in your select box as duplicate id's in objects are bad news bears.
angular.module('YOURAPPNAME', [])
.filter('myModelFilter', function() {
return function(myModel) {
if (myModel.id == 1) {
return myModel;
}
};
})
<div ng-controller="Models">
<select ng-model="myModel" ng-options="Model.name for Model in Models | myModelFilter" class="form-control"></select>
{{ {selected_Model:myModel.name} }} {{ {selected_Model:myModel.id} }}
</div>
EDIT: P.s.
Calling a controller and objects in your controllers "Model" and "Models" is confusing, I'd recommend choosing a different naming convention as AngularJS is an MVWhatever framework the term "Model" has a very different meaning to what you're using it for.
You could this on HTML side itself by using filter with strict checking true like ng-options="Model.name for Model in Models | filter: {id: 1}: true"
Markup
<div ng-controller="Models">
<select ng-model="myModel" class="form-control"
ng-options="Model.name for Model in Models | filter: {id: 1}: true" >
</select>
{{ {selected_Model:myModel.name} }} {{ {selected_Model:myModel.id} }}
</div>