ng-change method not executing - angularjs

I'm trying to pass the object selected in a to update the data of another object.
Here is the html
<select id="categoryListBox"
ng-model="category.selected"
ng-change="updateCategory(category.selected)"
ng-options="category._id as category.name for category in categories">
</select>
This renders
<select id="categoryListBox"
ng-model="category.selected"
ng-change="updateCategory()"
ng-options="category._id as category.name for category in categories"
class="ng-valid ng-dirty">
<option value="0" selected="selected">Test4</option>
<option value="1">Test5</option>
</select>
Here is my update function
$scope.updateCategory = function(){
console.log('hi');
}
My problem is that right now when the selected item changes the updateCategory method doesn't fires. I would like for whenever the option selected in the <select></select> changes that my $scope.updateCategory method fires. It would also be awesome if I could pass the category selected to this method.
Update here is the my initalization which populates the array categories
$scope.init = function (){
console.log('dfakjsdhf');
console.log(apiUrl);
$scope.category = {};
$scope.subcategory = {};
//$scope.categories = {_id: 1, name:'test'};
$http({ method: 'GET', url: apiUrl + '/categories'}).
success(function (data, status, headers, config) {
$scope.categories = data;
console.log($scope.categories);
}).
error(function (data, status, headers, config) {
console.log('error');
});
};

Just rename your ng-model from category.selected to something else. As per my understanding, In your code there is an ambiguity between ng-options category and ng-model category
<select id="categoryListBox"
ng-model="categorymodel"
ng-change="updateCategory(categorymodel)"
ng-options="category.id as category.name for category in categories">
</select>
DEMO

There is no need to pass the category.selected in your function. In your js controller it will be there in your scope, just use it in your updateCategory() function.
JSFiddle
Html:
<select id="categoryListBox"
ng-model="category.selected"
ng-change="updateCategory()"
ng-options="category.id as category.name for category in categories">
</select>
JS:
$scope.updateCategory = function(){
alert($scope.category.selected);
}

Related

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

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
}

Unable to set selected value in AngularJS

i have several select boxes on my edit form, now when the page loads data is loaded into it, this works for all textboxes and checkboxes but not selectboxes, i am unable to set the selected value for them i have googled so many things but i still cannot seem to find what i am doing wrong, this is my html:
<div class="form-group" ng-init="getRoles()">
<label for="roles">Role</label>
<select style="width: 100%;" data-toggle="select2" ng-model="form.role_id" ng-options="item.id as item.role for item in roles">
</select>
</div>
This is the function that gets and sets the user info in my controller:
$scope.getUserInfo = function() {
UserService.get($stateParams.id)
.success(function (data, status, headers, config) {
if (data.user != undefined)
{
$scope.form = data.user;
}
})
};
This the function that gets and sets the roles in my controller:
$scope.getRoles = function() {
RoleService.get()
.success(function (data, status, headers, config) {
if (data.roles != undefined)
{
$scope.roles = data.roles;
}
})
};
I have verified the returned data and it is indeed correct.
This is the returned JSON:
{"user":{"id":2,"email":"xxxxxxx#gmail.com","role_id":2,"institution_id":null,"is_active":1}}
And this is the returned roles JSON:
{"roles":[{"id":2,"role":"System"},{"id":3,"role":"Administrator"},{"id":4,"role":"Instructor"}]}
You need to write
ng-model="user.role_id"

Update model outside of controller

Just starting out on angular, not sure how to update a model out of a controller, or in fact if have my head around exactly what to do. I have an autocomplete field based on ion.autocomplete
HTML
<span ng-controller="IonAutocompleteController">
<label class="item item-input item-stacked-label">
<span class="input-label">Item Description</span>
<ion-autocomplete ng-model="model"
item-value-key="name"
item-view-value-key="view"
items-method="getTestItems(query)"
multiple-select="false"
placeholder="Bread, Milk, Eggs etc .."
items-clicked-method="itemsClicked(callback)"/>
</span>
<button class="button button-block button-royal" ng-click="scan()">Scan</button>
<div class="row">
<div class="col"><b>Item Name</b></div>
<div class="col" ng-model="name"></div>
</div>
Javascript
var myApp = angular.module('myApp', ['ionic','ngCordova','ion-autocomplete']);
myApp.config(['$ionicConfigProvider', function($ionicConfigProvider) {
$ionicConfigProvider.tabs.position('bottom')
}]);
myApp.controller('IonAutocompleteController', function ($scope,$http) {
$scope.model = "";
$scope.callbackValueModel = "";
$scope.getTestItems = function (query) {
console.log(query);
return $http.get('http://192.168.100.100/myApp/products/' + query).
success(function(data, status, headers, config) {
console.log(data);
}).error(function(data, status, headers, config) {
console.log("something went wrong")
});
};
$scope.itemsClicked = function (callback) {
console.log(callback);
$scope.name=callback.item.name;
console.log(callback);
$scope.callbackValueModel = callback;
}
});
What is happening here is the autoselect is grabbing data from a REST server and the results are place in the autocomplete. When the item is selected callback is returned in a json array. I want the callback to be place in ng-model="name" but it is out of the controller. Or I assume that is why it is not updating.
your ng-Model="name" binds to $scope.name in your controller. When data is returned from the REST call, just set $scope.name = data.
Two problems here.
1/ there is a missing </label>.
2/ should be using ng-bind NOT ng-model which is for inputs
You need to populate your view with autocomplete data based on what the success callback returns, not return the $http as an invocation.
$http.get('http://192.168.100.100/myApp/products/' + query).
success(function(data, status, headers, config) {
console.log(data);
// Do whatever you need to do to data before binding it,
//such as extracting a value from the JSON, etc.
$scope.model = data;
}).error(function(data, status, headers, config) {
console.log("something went wrong")
});
};

Filling a select not firing angular controller

I am trying to fill an HTML select using angular. I tested the API and got something like:
{"Countries":[{"Id":1,"Name":"Andorra"},{"Id":2,"Name":"France"}]}
The HTML is the following:
<form id="form" method="post" ng-submit="submit">
<select ng-model="model.currentCountry" ng-options="country.Id as country.Name for country in model.countries" ng-controller="CountryController">
<option value="">Country</option>
</select>
</form>
Then I have the JS code:
var application = angular.module('Application', []);
application.service('CountryService', function ($http) {
return {
GetList: function () {
return $http.get('api/countries');
}
}
});
application.controller('CountryController', function CountryController($scope, CountryService) {
alert("Country Controller");
$scope.model = {
currentCountry: '',
countries: []
}
CountryService.GetList()
.success(function (data, status, headers, config) {
$scope.model.countries = $scope.model.countries.concat(data)
})
.error(function (data, status, headers, config) { });
});
Somehow not even the alert in CountryController gets fired.
Any idea what am I missing?
In the success handler in your controller you have....
$scope.model.countries = $scope.model.countries.concat(data)
So you are concatting the Countries object from your example JSON, change that to this:
$scope.model.countries = $scope.model.countries.concat(data.Countries)
This way you are concatenating the actual array of countries to your model.countries.
Edit here is an example plnkr to play with

Using $watch for two variables angularjs

I have a pop up screen in which a user require to select from two drop down lists.
After the selections were completed i return the selections to the service and save them in an object.
app.service('OriginalService', [ '$modal',
function ($modal) {
var that = this;
this.filtersMananger = { // my-ng-models for the two drop-down-lists
firstFilter: "",
secondFilter: ""
};
this.openDialog = function(){
var modalInstance = $modal.open({
templateUrl: 'ModalScreen.html',
controller: 'ModalController',
resolve: {
filtersManagerObject: function () {
return that.filtersMananger;
}
}
});
modalInstance.result.then(function (filtersMananger) {
that.filtersMananger.firstFilter = filtersMananger.selectedFirstFilter;
that.filtersMananger.secondFilter = filtersMananger.selectedSecondFilter;
}, function () {
});
};
}
]);
The pop up html:
<div class="data-filters-container">
<div class="data-filter">
<label for="filter-data-drop-down">FIRST FILTER</label>
<select name="filterDataDropDown" ng-model="filtersMananger.selectedFirstFilter" ng-options="filter.value as filter.name for filter in filterDropDownItems"></select>
</div>
<div class="data-filter col-xs-4">
<label for="filter-data-drop-down">SECOND FILTER</label>
<select name="filterDataDropDown" ng-model="filtersMananger.selectedSecondFilter" ng-options="filter.value as filter.name for filter in filterDropDownItems"></select>
</div>
However, this change is important and i have to call to the controller which knows many other services to send them information regarding this change.
In order to do it i used a watch function in the controller:
$scope.$watch('OriginalService.filtersMananger.firstFilter + OriginalService.filtersMananger.secondFilter', function (newVal, oldVal) {
if (newVal !== oldVal) {
DO SOME LOGIC
}
});
I compare between newVal and oldVal because when the app is uploaded the event is called and we enter to this function.
The problem is that the newVal is contains only the value of the secondVariable.
Is there any idea why the newVal is not contains also the first variable?
Use $watchCollection:
$scope.$watchCollection('[serviceName.Object.firstVariable,serviceName.Object.secondVariable]', function (newValues, oldValues) {
});
Or if you're using angular 1.3 use $watchGroup:
$scope.$watchGroup(['serviceName.Object.firstVariable','serviceName.Object.secondVariable'],function(newValues, oldValues){
})
You could also use ng-change on your select.
The ng-change will call a function that do your logic
<div class="data-filters-container">
<div class="data-filter">
<label for="filter-data-drop-down">FIRST FILTER</label>
<select name="filterDataDropDown" ng-change="checkFilterOne()" ng-model="filtersMananger.selectedFirstFilter" ng-options="filter.value as filter.name for filter in filterDropDownItems"></select>
</div>
<div class="data-filter col-xs-4">
<label for="filter-data-drop-down">SECOND FILTER</label>
<select name="filterDataDropDown" ng-change="checkFilterTwo()" ng-model="filtersMananger.selectedSecondFilter" ng-options="filter.value as filter.name for filter in filterDropDownItems"></select>
</div>
It will call the function when your model will change that is like a $watch.

Resources