With the angular-bootstrap-duallistbox component, documented here, and using the $http service, How do I set the selected elements on it?
Here is the used code:
HTML:
<select ng-options="obj as obj.name for obj in authorizations"
multiple
ng-model="selections"
bs-duallistbox
></select>
Javascript:
angular.module('demoApp', ['frapontillo.bootstrap-duallistbox'])
.controller('ProfileAutAsigController',
function ($scope, $http, Authorization) {
$scope.authorizations = [];
$scope.selections = [];
Authorization.query().$promise.then(function (response) {
$scope.authorizations = response;
return $http.get("api/profileAut/1/authorizations");
}).then(function (payload) {
//This doesn't set the selected items. Specifying an
//array manually doesn't work either.
//$scope.selections = [{id:1, name:'Text'},{id:3, name:'Photos'}];
$scope.selections = payload.data;
}, function (payload) {
//Error happened
console.log(payload.error);
});
});
Thanks.
To populate angular bootstrap dual list box you should use track by instead of as like this:
You have to use track by instead as in ng-options
Instead this:
<select ng-model="selected" ng-options="av as av.name for av in available" multiple bs-duallistbox></select>
Uses:
<select ng-model="selected" ng-options="av.name for av in available track by av.id" multiple bs-duallistbox></select>
At last I couldn't make work angular-bootstrap-duallistbox with $http service. I used instead this angular directive, which worked with $http:
https://github.com/alexklibisz/angular-dual-multiselect-directive
Be sure of following the items json format. Read the example.
Related
I know there are several similar topics already but I found none that really matches my problem.
When opening my AngularJS app/website I am loading two arrays of objects (both are of the same type). One list contains all possible values (called sources here) and the other list is a selection of elements from the first.
My goal is display all sources as checkboxes. The ones from the second list have to be preselected, the rest not. Now the user can select/deselect checkboxes. If he does so I need to inform the server (with the source.id).
What I got so far:
exampleApp.controller('testController', [ '$scope', '$http', function($scope, $http) {
$scope.sources = [];
$scope.selectedSources = [];
$scope.changeSource = function(source) {...};
})
and
<div ng-repeat="source in sources">
<input
type="checkbox"
name="source.name"
value="{{source.id}}"
ng-model="??"
ng-change="changeSource(source.id)"
> {{source.name}}
</div>
What I can't figure out is how I can get ng-model to preselect the right checkboxes and how to get the new (and old) values to changeSource(). Is there an elegant way of doing that?
Example (Pseudo code only):
Sources = [{id=1, name=test1},{id=2, name=test2}, ...]
SelectedSources = [{id=2, name=test2}]
Now what I need are checkboxes like this:
[ ] test1 [x] test2
where all elements from sources are checkboxes and the ones from selectedsources are preselected. Changes of the selection can be stored in selected sources (as objects) and have to trigger my changeSource() function so that I can inform my server.
Set the selected/unselected state in a property inside each of the objects in Sources array(initialize it based on whats present in selectedArray)
$scope.sources.forEach(function(source) {
source.selected = isSelected(source);
})
function isSelected(selectedSource) {
return !!$scope.selectedSources.find(function(s) {
return s === selectedSource || s.id == selectedSource.id;
})
}
Here's a working plunker link
I didn't understood your question very well, but if i'm not mistaken, you want to fill the second collection only with the selected items from the first one, right? If it's the case, you could turn your second collection into a returning function with a filter of the first inside, as follows:
In your controller:
exampleApp.controller('testController', [ '$scope', '$http', function ($scope, $http) {
$scope.sources = [];
/* ... */
$scope.getSelectedSources = function () {
return $scope.sources.filter(function (val) {
return val.selected;
});
};
})
In your template:
<div ng-repeat="source in sources">
<input
type="checkbox"
name="source.name"
value="{{source.id}}"
ng-model="source.selected"
ng-change="changeSource(source.id)"
> {{source.name}}
</div>
<div ng-repeat="source in getSelectedSources()">
<input
type="checkbox"
name="source.name"
value="{{source.id}}"
ng-model="source.selected"
ng-change="changeSource(source.id)"
> {{source.name}}
</div>
Hi this may be help you to get new & old value.
$scope.$watch('sources', function (oldval, newval) {
console.log(oldval + newval);
});
I'm trying to write a simple AngularJS program which makes REST calls to an API that gives data on exchange rates. the app deals with exchange rates, and i'm doing this mainly for educational purposes.
I'm have an issue while attempting to two-way bind data between a select element in the HTML:
<select id="currencySelect"
ng-model="search"
ng-options="currency for (currency, rate) in exRates.rates">
</select>
And my controller:
(function () {
"use strict";
angular.module("exchangeRates")
.controller('getRates', function($scope, $http){
$scope.$watch('search', function() {
fetch();
});
$scope.search = "USD";
function fetch(){
$http.get("http://api.fixer.io/latest?base=" + $scope.search )
.then(function(response){
$scope.exRates = response.data;
});
}});
}());
'search' is bound to the HTML element via ng-model, and works perfectly for the default value set at "USD". However, when I use the select element to select another type of currency, the data bound to 'search' is the rate in the (currency, rate) -- key, value pair.
I want it to take the currency(key) which is being displayed in the select element and bind that to 'search' instead of the rate(value).
For example: If I choose "EUR" in the select element, 'search' is bound to 0.90318 instead of "EUR". The GET request then tries:
http://api.fixer.io/latest?base=0.90318
which does not work.
It may help to look at a sample JSON excerpt:
Source
{ "base":"USD",
"date":"2016-07-13",
"rates": {
"AUD":1.3111,
"BGN":1.7664,
"BRL":3.2981,
"CAD":1.3053,
"CHF":0.98528,
"CNY":6.6905,
"CZK":24.416,
"DKK":6.7177,
"GBP":0.75323,
"HKD":7.7576,
"HRK":6.7677,
"HUF":283.05,
"IDR":13046.0,
"ILS":3.8685,
"INR":67.03,
"JPY":104.61,
"KRW":1143.0,
"MXN":18.316,
"MYR":3.9432,
"NOK":8.4127,
"NZD":1.3687,
"PHP":47.13,
"PLN":3.979,
"RON":4.0565,
"RUB":63.801,
"SEK":8.5231,
"SGD":1.346,
"THB":35.18,
"TRY":2.8944,
"ZAR":14.333,
"EUR":0.90318
}
}
Example of the user interface
You were close, just need to adjust your ngOptions syntax slightly:
ng-options="currency as currency for (currency, rate) in exRates.rates"
Easy to remember with value as text for item/obj in collection
I've created a small sample of what is happening.
http://plnkr.co/edit/py9T0g2aGhTXFnjvlCLF
Basically, the HTML is:
<div data-ng-app="app" data-ng-controller="main">
<select class="ui dropdown" id="ddlState" data-ng-options="s.name for s in states track by s.id" data-ng-model="selectedState"></select>
<select class="ui dropdown" id="ddlCity" data-ng-options="c.name for c in cities track by c.id" data-ng-model="selectedCity"></select>
</div>
And the javascript is:
angular.module("app", [])
.controller("main", function($scope, $timeout) {
$scope.selectedState = {id:1,name:"A"};
$scope.selectedCity = {id:1,name:"A.1",stateId:1};
$scope.states = [{id:1,name:"A"},{id:2,name:"B"},{id:3,name:"C"}];
var fakeDataSource = [
{id:1,name:"A.1",stateId:1},
{id:2,name:"A.2",stateId:1},
{id:3,name:"A.3",stateId:1},
{id:4,name:"B.1",stateId:2},
{id:5,name:"B.2",stateId:2},
{id:6,name:"B.3",stateId:2},
{id:7,name:"C.1",stateId:3},
{id:8,name:"C.2",stateId:3},
{id:9,name:"C.3",stateId:3}
];
$scope.$watch("selectedState", function(n,o){
if (n !== o)
$scope.selectedCity = null;
$scope.cities = fakeDataSource.filter(function(x){
return n.id === x.stateId;
});
$timeout(function(){
$(".ui.dropdown").dropdown().dropdown("refresh");
});
})
$timeout(function(){
$(".ui.dropdown").dropdown();
})
})
The problem is when I change the first dropdown to value 'B' or 'C', the value of second dropdown does not change, even it is changed in angular model.
You guys can notice that I've the line $(".ui.dropdown").dropdown().dropdown("refresh") to refresh the values but does not work.
I tried destroy and recreate using $(".ui.dropdown").dropdown("destroy").dropdown() but still does not work.
Any help?
Simply using ngModel won't make the values change dynamically. Take a look at the documentation here: https://docs.angularjs.org/api/ng/directive/ngModel
You can bind the values using ngBind or what I have done is do an onChange to then check the value and change your second drop down accordingly. Something like:
$("#ddlState").on("change", function(e) {
//check $scope.selectedState for it's value, and change #ddlCity/$scope.selectedCity accordingly
});
Here is the plunkr i have created.
Basically i am facing 2 issues with this piece of code -
I need help loading months in the drop down and
When month is changed in the dropdown from headerController, the sales for that month is displayed in detailController. I am trying to create a dependency between multiple controllers using a service.
I will appreciate any help fixing these 2 issues.
You can use $broadcast service for event purposes. Following is the link which explains the use of $broadcast and communicating between two controllers.
enter code herehttp://plnkr.co/edit/d98mOuVvFMr1YtgRr9hq?p=preview
You could simply achieve this by using $broadcast from one controller in $rootScope and listen that event in $scope using $on. Though I would suggest you to use service that will share data among to controller. Using dot rule will reduce your code. Take a look at below optimized code. Also you could replace your select with ng-repeat with ng-option to save object on select.
Markup
<div data-ng-controller="headerController">
<h3>Select Month</h3>
<select id="month" ng-model="sales.selectedMonth"
ng-options="month.monthId for month in sales.monthlySales">
</select>
</div>
<div data-ng-controller="detailsController">
<h3>Sales for Month</h3>
<div ng-bind="sales.selectedMonth"></div>
</div>
Code
app.service('valuesService', [function() {
var factory = {};
factory.sales = {}
factory.sales.salesForMonthId = 10;
factory.sales.months = [1, 2];
factory.sales.monthlySales = [{monthId: 1,sales: 10}, {monthId: 2,sales: 20}];
factory.sales.selectedMonth = factory.sales.monthlySales[0];
return factory;
}]);
app.controller('headerController', ['$scope', 'valuesService',
function($scope, valuesService) {
$scope.sales = {};
getData();
function getData() {
$scope.sales = valuesService.sales;
}
}
]);
app.controller('detailsController', ['$scope', 'valuesService',
function($scope, valuesService) {
$scope.sales = {};
getData();
function getData() {
$scope.sales = valuesService.sales;
}
}
]);
Demo Plunkr
I can see the months are already loading fine.
For proper data binding to work across service and controller, you would need to bind one level above the actual data, resulting a dot in your expression. This is because javascript doesn't pass by reference for primitive type.
In service:
factory.data = {
salesForMonthId: 0
}
In controller:
app.controller('detailsController', ['$scope', 'valuesService',
function ($scope, valuesService) {
$scope.values = valuesService.data;
}
]);
In template:
<div>{{values.salesForMonthId}}</div>
Plunker
The Select element does get populated by the http request, but the options in the select element are not updating as the ng-model is changed. I am new to angularJs so im assuming its a simple fix. I have tried many variation with no positive results.
<script>
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope, $http) {
$http.get('http://graph.facebook.com/platform')
.success(function(data) {
})
});
</script>
<body ng-controller="MainCtrl">
Search:
<input type="search" ng-model="searchText" />
<select>
<option ng-repeat="item in data | filter: searchText">{{item}}</option>
</select>
<br>
<pre>{{ data | json}}</pre>
</body>
http://plnkr.co/edit/C39yVDsG3OcfvwjVSxP9?p=preview
TarranJones, this Plunker should clear things up. Hard to give you a 100% clear answer without a look at your data. You should be able to figure it out from here.
http://plnkr.co/edit/UYm0SwtU6ePZkZLx2w2U?p=preview
To Answer your question in the comments I would replace:
app.controller('MainCtrl', function($scope) {
$scope.colors = [
{name:'black', shade:'dark'},
{name:'white', shade:'light'},
{name:'red', shade:'dark'},
{name:'blue', shade:'dark'},
{name:'yellow', shade:'light'}
];
});
With:
app.controller('MainCtrl', function($scope, $http) {
$http.get('http://www.foo.com')
.success(function(data) {
$scope.colors = data;
})
.error(function() {
console.log('My name is Error, now eat it!);
});
});
Make sure to inject the $http.
Plunker here. http://plnkr.co/edit/UYm0SwtU6ePZkZLx2w2U?p=preview
UPDATE:
Tarran also ran into the problem of filtering a single returned JSON object from an API. Angular Filters can only accept arrays and so would not accept the object. In order for Tarran to filter the object he must first iterate through the object and store the object properties to an array. Once the array is then returned to the $scope you can filter the results. The plunker and code is provided below: http://plnkr.co/edit/9M3zZFN5jyV8w7fg7EE3?p=preview
Controller:
$http.get('http://graph.facebook.com/4')
.success(function(data) {
//CREATE AN EMPTY ARRAY
result = [];
//ITERATES THROUGH THE OBJECT SAVING THE OBJECTS PROPERTIES TO ARRAY
for (var i in data) {
if (data.hasOwnProperty(i)) {
//PUSHES THE PROPERTIES ONTO THE ARRAY
result.push(data[i]);
}
}
//SETS THE NEW DATASET TO THE ARRAY AND RETURNS TO $SCOPE
$scope.dataset = result;
});
HTML:
{{dataset}}
<BR>
<BR>Search:
<input type="search" ng-model="searchText" />
<BR>
<BR>
<select>
<option ng-repeat="data in dataset | filter: searchText">{{data}}</option>
</select>
Try to init your data as object before all.
$scope.data = {}
Or in HTML :
<div ng-controller="FetchCtrl" data-ng-init="data={}; fetch()">