Update model outside of controller - angularjs

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")
});
};

Related

Where to persist data used by many controllers in AngularJS? [duplicate]

I'm new to angular and I'm wondering how I can share a variable between controllers in angular. I'm using the following scripts -
In Main.js:
function MainCntl($scope) {
---code
}
function SearchCtrl($scope, $http) {
$scope.url = 'http://10.0.0.13:9000/processAdHoc';
$scope.errorM = "No results";
$scope.search = function() {
$http.post($scope.url, { "data" : $scope.keywords}).
success(function(data, status) {
$scope.status = status;
$scope.data = data;
$scope.result = data;
alert('yes');
})
.
error(function(data, status) {
$scope.data = data || "Request failed";
$scope.status = status;
alert('no');
$scope.result = "failed";
});
};
}
In Index.html
<body ng-controller="MainCntl" >
---code
<div ng-controller="SearchCtrl">
<form class="well form-search">
<div class="ui-widget">
<label for="tags"></label>
<a ng-click="search()"><input type="image" src="../../images/search1.png" class="searchbox_submit" /></a>
<input ng-model="keywords" placeholder="Shadow Search" id="tags" class="input-medium search-query rounded" />
</div>
</form>
</div>
---code
<p ng-model="result">
{{result}}
</p>
</body>
Everything works well with the ajax I'm sending data and receiving a response, my question is as follows:
In the SearchCtrl function I have a variable called $scope.result that is later referred to in Index.html. If I insert the html code that contains that variable into the SearchCtrl controller it works fine but if it is in the MainCtrl controller it does not work. How can I share this variable between the controllers.
Thanks ahead
Use a service and inject it to both controllers and refer your scope vars to the services variable.
Example:
angular.module("yourAppName", []).factory("myService", function(){
return {sharedObject: {data: null } }
});
function MainCtrl($scope, myService) {
$scope.myVar = myService.sharedObject;
}
function SearchCtrl($scope, $http, myService) {
$scope.myVar = myService.sharedObject;
}
In your template do:
{{myVar.data}}
See an example Uses Angular v1.1.5
The reason you put it in an inner object is to preserve your references, if you keep it without a "sharedObject", and change that object, your binding will be pointing to the old reference and wouldn't show anything in the template.

angularjs not updaing propeties when promises used

I am using service to get JSON object using promises. It is then converted into array and assign to a property which is in $scope object. The problem is that array is not getting updated or any properties inside promise then() method.
Controller
var searchController = function ($scope, $SPJSOMService) {
$scope.myName = "old name";
$scope.getUsers = function ($event) { //called on button click
$event.preventDefault();
var queryText = "test user";
$SPJSOMService.getUsers(queryText)
.then(function myfunction(users) {
$scope.userCollection = JSON.parse(JSON.stringify(users)).d.results;
// $scope.$apply(); this line throwing error. $rootScope in progress
$scope.myName = "new name"; //not getting updated
}, function (reason) {
alert(reason);
});
};
};
Service
var SPJSOMService = function ($q, $http, $rootScope) {
this.getUsers = function (userToSerach) {
var deferred = $q.defer();
$http({
url:'some url',
method: "GET",
headers: {
"accept": "application/json;odata=verbose",
"content-Type": "application/json;odata=verbose"
}
})
.success(function (data, status, headers, config) {
deferred.resolve(data); //successfully return data
})
.error(function (data, status, headers, config) {
deferred.reject(data);
});
return deferred.promise;
};
};
Updated
index.html
<div ng-include="'Search.html'">
</div>
<div ng-include="'searchResults.html'"></div>
search.html
<div id="containerDiv" ng-controller="searchController as search">
<input class="button" type="button" ng-click="getUsers($event);" value="Search" id="btnSearch" />
</div>
searchResults.html
<div ng-controller="searchResultController as result">
<table >
<thead>
<tr>
<th>Name</th>
<th>EMail</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in userCollection">
<td>{{$index}} {{item.userName}}</td>
<td>{{$index}} {{item.userEmail}}</td>
</tr>
</tbody>
</table>
</div>
So search.html returns the data by calling the service and I am trying to pass it to the page namely searchResults.html which have its own controller.
$scope.users = $scope.userCollection;
Service class correctly returning data, but the problem is inside then(), which is not updating $scope.userCollection, hence UI is not getting updated.
Please help me out, what am I missing here.
In angular controllers can bind to the view in two ways:
"controller as"
through scope
It looks you are using the "controller as" flavor here...
<div ng-controller="searchResultController as result">
Refer to https://docs.angularjs.org/api/ng/directive/ngController for more information.
Change your controller code to:
var searchController = function ($scope, $SPJSOMService) {
//note use of "this" instead of "$Scope"
var _this = this;
_this.myName = "old name";
_this.getUsers = function ($event) { //called on button click
$event.preventDefault();
var queryText = "test user";
$SPJSOMService.getUsers(queryText)
.then(function myfunction(users) {
_this.userCollection = users.d.results; //You don't need JSON.parse not JSON.stringify
_this.myName = "new name";
}, function (reason) {
alert(reason);
});
};
};
and in your view use the controller "alias":
<div ng-controller="searchResultController as result">
...
<tr ng-repeat="item in result.userCollection">
...
You have to push it to the new array I think. Have you tried this in your then statement?
$scope.myName.push("new name");
It should put it in the existing array. Let me know if it works.

Display Angular Loading Bar in a specific $http request NOT in the whole module

When I used the chieffancypants loadingBar, the loading bar appears from the start of the loading of the page and to every $http request that i make,
I want to display only the loading bar progress when I click the search button which retrieves a large amount of data.
var mtg = angular.module('mtgApp',['ui.bootstrap','chieffancypants.loadingBar','ngAnimate']);
mtg.controller('mtgController',function($scope,$http,$location)
{
var apiBaseUrl = "http://sampleAPIURL.com";
$scope.token = "sampletoken";
$scope.processForm = function()
{
$http({
method: 'POST',
url: apiBaseUrl + 'flight/search?token=' + $scope.token,
data: {
//my json request
//flightForm.from,
//flightForm.to,
//flightForm.date
}
}).success(function(data, status, headers, config){
$scope.displayResults(data.searchId);
}).error(function(data, status, headers, config){
console.log("Check For Errors");
});
}
$scope.displayResults = function(searchId)
{
$http.get(apiBaseUrl + 'Flight/results/'+searchId+'?$top=50&token=' + $scope.token).success(function(data)
{
$scope.results = data.flightResult;
$location.path('/search/results');
});
};
});
In my search
<form ng-controller = "mtgController">
<input type = "text" ng-model = "flightForm.from">
<!--uses $http request to get the suggested location-->
<input type = "text" ng-model = "flightForm.to">
<!--uses $http request to get the suggested location-->
<input type = "text" ng-model = "flightForm.date">
<input type = "button" ng-click = "processForm()" value = "Search">
</form>
In my html search/results
<form>
<div ng-controller = "mtgController">
<div ng-repeat = "result in results">
//{{result.details}} and so on and so on
</div>
</div>
</form>
I want the loading bar appears only when I click the search button while waiting for the response data and go to the results page
Try to add after data:
success: function (test) {
$("#mtg.controller").val('');
$("#success").html(test);
$("#mtg.controller").removeClass("disabled");
}
});
});
});
Also, you can do success: function instead of succes(function for what you already have.

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"

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

Resources