Angularjs Dependent State->cities dropdown, retrieve cities from http.get service - angularjs

I am looking for a way to use an http.get service to retrieve the cities from the federated state they belong. I create a dependent dropdown of cities from a choosen state.
Here is a working fiddle to serve as a base to a dinamic version:
http://jsfiddle.net/amrigo/v8u7v4af/
I meant to have states and cities:
function CountryController($scope) {
$scope.countries = {
'Michigan': {
'Detroit': [],
'Flint': []
},
'Texas': {
'Austin': [],
'Houston': []
},
'California': {
'Los Angeles': [],
'San Francisco': []
}
};
}
How can i write a factory that receives the state id and adjust to the JSON format: ('Los Angeles': [],'San Francisco': []).
.factory('citiesByState', function($http) {
return {
getVersion: function(id) {
return $http.get('http://www.service.com/ckeck_cities.php')
.then(function(response) {
return response.data;
});
}
};
});
<select class="form-control input-lg" id="country" ng-model="states" ng-options="country for (country, states) in countries">
<option value=''>Select</option>
</select>
<select class="form-control input-lg" id="state" ng-disabled="!states" ng-model="cities" ng-options="state for (state,city) in states">
<option value=''>Select</option>
</select>

The factory will fetch the cities by given state and save it in a state->cities map.
.factory('citiesByState', function($http) {
return {
locationData: {},
getCities: function(id) {
var that = this;
return $http.get('http://www.service.com/ckeck_cities.php?state='+id)
.then(function(response) {
that.locationData[id] = response.data;
});
}
};
});
You then inject the service into your controller and use that state->cities map to update your UI.
function CountryController($scope, $citiesByState) {
$citiesByState.getCities(1); // pass your state id
$scope.cities = $citiesByState.locationData; //cities will contain your data for the given state when the response is received
}

Related

Why won't ng-options populate this dropdown?

Here's my json
[{"year":"1980","Manufacturer":"Oldsmobile","Model":"Cutlass","Product":""},{"year":"1980","Manufacturer":"Oldsmobile","Model":"Sierra","Product":""},{"year":"1980","Manufacturer":"Toyota","Model":"4Runner","Product":""},{"year":"1980","Manufacturer":"Ford","Model":"Fiesta","Product":""},{"year":"1980","Manufacturer":"GMC","Model":"Terrain","Product":""}]
and my HTML
<label class="item item-select">
<span class="input-label">
Select
</span>
<select ng-model="data.make" ng-options="make.Manufacturer for make in
makes">
</select>
</label>
I'm probably missing something very basic here. The data is accessible in $scope.data.makes in the console.
Edited to add my javascript
function ($scope, $stateParams, getProducts) {
$scope.data = {
"year" : $stateParams.year,
"make" :""
}
$scope.data.makes = getProducts.getMakesByYear($scope.data.year).then(function(data){})
}
edited to add my function:
var ret = {
all: function(){
return $http.get(api_url).then(function(resp){
return resp.data;
});
},
single: function(id){
return $http.get(api_url+"search?Id="+id).then(function(resp){
return resp.data;
});
},
getMakesByYear: function(year){
return $http.get(car_url+"search?year="+year).then(function(resp){
return resp.data;
});
}
}
ret.all();
return ret;
}]);
Your code isn't populating because you're setting data.makes to a promise instead of setting it to the array that the promise returns
you can fix it by calling the function when the controller initializes
function ($scope, $stateParams, getProducts) {
$scope.data = {
"year" : $stateParams.year,
"make" :"",
"makes" : []
}
getProducts.getMakesByYear($scope.data.year).then(function(data){
$scope.data.makes = data;
})
}
also... make sure you're using the correct variable data.makes instead of makes
<select ng-model="data.make" ng-options="make as make.Manufacturer for make in data.makes">
If the function is returning usable json then it should work with data.makes instead of just makes because makes is not directly on the scope

Angular 1:Build dropdown box dynamically

I am new to Angular 1,so I am stuck with building a dropdown box dynamically using angular.
Below is my code
var app = angular.module('myApp', []);
app.controller('TestCtrl', function($scope, $http) {
I have created an onchange function getTypeName() and have passed the parameters using get method and retrieved the result as json .
$scope.getTypeName = function (type) {
$http.get('get-type-name',
{ params:
{
type: type
}
}).then(
function(response){
var data = response.data;
for(i = 0; i < data.length; i++) {
//code to build dropdown
}
},
);
}
});
Below is my response,
[
{"id":"001","name":"ABC"},
{"id":"002","name":"DEF"},
{"id":"003","name":"GHI"}
]
I want to build a dropdown box using this response within the get method function success using for loop.Please provide a solution to solve this out.
you do like this
in app.js
$scope.getTypeName = function (type) {
$http.get('get-type-name',
{ params:
{
type: type
}
}).then(
function(response){
$scope.data = response.data;
},
);
}
});
in your html
<select id="ddl" model="ddldata" typeof="text"required>
<option data-ng-repeat="ProjectName in data" value="{{ProjectName.id}}" ng-bind={{ProjectName.name}}">
</select>
You can try this,
$scope.yourOptions = [];
$scope.getTypeName = function (type) {$http.get('get-type-name',
{ params:
{
type: type
}
}).then(
function(response){
var data = response.data;
$scope.yourOptions = data;
},
);
}
});
in html,
<select class="form-control" ng-model="whatever" >
<option ng-repeat="x in yourOptions " value="{{x.id}}">{{x.name}}</option>
</select>
Here is an example of dynamically populating select options from an http get https://plnkr.co/edit/7PS7LBBNZA2cNzMorrB9?p=preview
<select ng-model="selectedItem">
<option ng-repeat="o in options">{{o.name}}</option>
</select>
$scope.getTypeName = function() {
$http.get('https://jsonplaceholder.typicode.com/users').then(
function(result) {
$scope.options = result.data;
},
function(error) {
console.log(error);
}
);
};

Change in data made by $http inside a factory is not reflected to the DOM

I'm trying to create a dynamic form based on an object.
For example: I'd like that generated select boxes will contain options if given, otherwise a factory will fetch them using ajax, something like this:
Markup:
<select ng-repeat="select in selects"
ng-init="options = refactor.options(select)"
ng-options="option in options">
</select>
Controller:
myApp.controller('MyCtrl', function($scope, refactor) {
$scope.refactor = refactor;
$scope.selects = [
{ text: "Country", value="chosen.country", options=["France", "England"] },
{ text: "Gender", value="chosen.gender", options="/gender" }
]
});
Factory:
myApp.factory('refactor', function($scope, $http) {
return {
options: function(select) {
if(typeof(select.options) === 'object') { return select.options };
// otherwise assume select.options is
// a path to fetch options by ajax:
$http.get(select.options).success(function(data) {
select.options = data; // data == ['male', 'female']
});
return []; // placeholder until promise is fulfilled
}
}
})
The data ( $scope.selects ) gets updated as expected, yet the DOM is not, which probably means refactor.options() is not being invoked again in response to the change. I tried to force an update by passing the scope object to the factory and invoke $apply on it, but it doesn't work.
What am I missing?
You need to use ng-init="data = refactor.options(select)" so after getting data from ajax data would be filled up with options then you could use ng-options as instead of ng-options="option in data.options".
Markup
<select ng-repeat="select in selects"
ng-init="data = refactor.options(select)"
ng-options="option in data.options">
</select>
You should try this
myApp.factory('refactor', function($scope, $http) {
return {
options: function(select) {
var menuItems={
options:[]
}
if(typeof(select.options) === 'object'){
menuItems.options=select.options
};
// otherwise assume select.options is
// a path to fetch options by ajax:
$http.get(select.options).success(function(data) {
select.options = data;
menuItems.options=data;// data == ['male', 'female']
});
return menuItems; // placeholder until promise is fulfilled
}
}
});
Then inside your view it should go like this
<select ng-repeat="select in selects"
ng-init="menuItems= refactor.options(select)"
ng-options="option in menuItems.options">
</select>

make an ajax call when radio buttons are clicked and update the model value with response in angular

I can't seem to find out how to do make an ajax call and set the '$scope.ticker' model with the response in angular. Basically, this is doing an ajax call to get the last price of the ticker (btc_usd, btc_eur, or btc_rur).
Such that "$scope.last" is always the last price of whichever ticker radio button is selected.
<label><input type="radio" name="currency" value="btc_usd" ng-model="currency"> USD</label>
<label><input type="radio" name="currency" value="btc_eur" ng-model="currency"> EUR</label>
<label><input type="radio" name="currency" value="btc_rur" ng-model="currency"> RUR</label>
$scope.ticker = quote.ticker($scope.currency).then(function(data){
var last = data.ticker.last;
$log.log('last', last);
$scope.ticker = last;
$scope.last = last;
});
app.factory('quote', function($http, $log) {
return {
ticker: function(currency){
$log.log('ticker.currency', currency);
//return the promise directly.
return $http.get('/api/last/'+currency)
.then(function(result) {
//resolve the promise as the data
return result.data;
});
}
};
});
First all I would change ng-model to ng-model="$parent.currency".
Second - we can write radios with ng-repeat:
HTML:
<label ng-repeat="value in list">
<input type="radio" name="currency" ng-model="$parent.currency" ng-value="value.name" />{{value.name}}
</label>
when controller:
$scope.list = [{
name: "USD"
}, {
name: "EUR"
}, {
name: "RUR"
}];
$scope.currency = 'USD';
$scope.$watch(function () {
return $scope.currency;
},
function (newValue, oldValue) {
console.log(newValue);
}, true);
Now from $watch you can run ajax request based on newValue
Demo Fiddle

Custom Filter for AngularJS based on a boolean

I am trying to write a custom filter. It's purpose is to do one of three things, based on a drop down menu. It needs to either show only hidden items, only notHidden items, or all items.
Here is my drop down menu.
<select class="span1" ng-model="itemfilter.hidden'">
<option value="">All</option>
<option value="hidden">Hidden</option>
<option value="shown">Shown</option>
</select>
Here is the HTML for the ng-repeat and filter
<div ng-repeat="item in items | hiddenFilter:itemfilter.hidden:'hidden"> </div>
Here is the Custom Filter
app.filter('hiddenFilter', function($_ ) {
return function( items, show_or_hide, attribute ) {
var shownItems = [];
$_.each(items, function(item) {
if(show_or_hide === 'shown') {
if (item[attribute] === true)
shownItems.push(item);
} else{
if (item[attribute] !== true)
shownItems.push(item);
}
});
return shownItems;
};
});
I am having trouble figuring out how to make the drop down menu change what this filter displays, any help would be greatly appreciated.
Edits --
Once I passed in the attribute correctly I started getting different results. The all and hidden options now show only nonHidden items, and the shown options shows only hidden items. Still not sure where I am going wrong.
Edit 2 --
Tried to make a jsfiddle for it here http://jsfiddle.net/mindstormy/RVB8A/1/
Fixed the code for you. Working Demo
<div ng-app="app" ng-controller="exampleCtrl">
<select class="span1" ng-model="itemfilter.hidden">
<option value="all">All</option>
<option value="hidden">Hidden</option>
<option value="shown">Shown</option>
</select>
<div ng-repeat="item in items| hiddenFilter:itemfilter.hidden:'hidden'">{{item.name}}, {{item.hidden}}</div>
</div>
var app = angular.module('app', []);
app.controller('exampleCtrl', function ($scope) {
$scope.items = [{
name: 'Foobar',
hidden: true
}, {
name: 'Foobar',
hidden: false
}, {
name: 'Barfoo',
hidden: true
}, {
name: 'Barfoo',
hidden: false
}, {
name: 'FB',
hidden: false
}];
$scope.itemfilter = {};
$scope.itemfilter.hidden = "all";
});
app.filter('hiddenFilter', function () {
return function (items, show_or_hide, attribute) {
var shownItems = [];
if (show_or_hide === 'all') return items;
angular.forEach(items, function (item) {
if (show_or_hide === 'shown') {
if (item[attribute] === true) shownItems.push(item);
} else {
if (item[attribute] !== true) shownItems.push(item);
}
});
return shownItems;
};
});

Resources