DOM loading before the promise defer completes - angularjs

I have a model that I am using to hold my data in angular:
var FuelProcessingModel = function (carrierService) {
this.myArray = [];
};
That model has an array of MyObjects that I get from the DB:
var MyObject = function () {
//stuff
}
I update this using a REST call:
$scope.add = function () {
var myObject = new MyObject();
fuelProcessingService.add(myObject).then(function(result) {
$scope.model.MyObjects.push(result.data);
});
};
Here you can see I want to push the result to the array so that it is added on the screen. But the problem is the DOM loads before that happens.
service to hit the Server:
this.add = function (myObject) {
var deferred = $q.defer();
$http({
method: "POST",
url: "theServer",
data: myObject,
}).success(function (data) {
deferred.resolve(data);
});
return deferred.promise;
}
The REST service adds to the Database and then returns the updated object
I thought that $q.defer() would cause the DOM to wait to load until the result is returned so that the newly added item shows up.
What am I missing?
UPDATE
I tried doing this but I still have the same problem. The push call is not being called before the DOM loads the page, so the user never sees the added item.
this.add = function (myObject) {
return $http({
method: "POST",
url: "theServer",
data: myObject,
}).success(function (data) {
return data;
});
Html that creates and uses the object
<div ng-repeat="myObject in model.MyObjects" style="margin-bottom: 2%">
//A table of myObjectData
<button class="btn btn-success" ng-click="add()">Add My Object</button>
</div>

Here is what happens in Angular.
Initial html is rendered (also called template html).
Angular boostraps, and then does the necessary binding and the view is updated.
Angular watches for changes and if there is a change in data, view is updated automatically.
When you bind the array to the view the, it renders what is available. When you add some new element to the array later the view should automatically update. You do not need to bother with creating your own promise just do
return $http...

Related

My $scope value not updating

updated object is not getting without using location.reload
Hi i will get list of objects from API where i have to update one value,After updating that value in modal popup i am not able to get new updated value without using location.reload. Is there any other solution for this.i am using two different controllers.
Will get list of objects from this
$scope.groups=response.data
will ng-repeat this groups where i will have edit button for every line,Once i click edit button popup will open
$scope.editGroup = function(u) {
$scope.groupName=u.groupName;
$scope.groupId=u.groupId;
ModalService.showModal({
templateUrl: 'app/components/modal/editGroupDetails.html',
controller: "ModalController",
scope: $scope
}).then(function(modal) {
modal.element.modal();
modal.close.then(function(result) {
$scope.message = "You said " + result;
});
});
};
Next once i edit the GroupName i will click submit
$scope.updateGroupName=function(){
var data={
"groupId": $scope.groupId,
"groupName": $scope.groupName
}
url=globalUrlConfig.globalAdminApi+globalUrlConfig.updateGroup+$scope.schoolId;
$http({
method: 'PUT',
url: url,
data: data,
}).success(function(response) {
console.log(response)
if(response._statusCode==200){
alert(response.data);
location.reload();
}
else{
alert("not updated")
}
})
}
Without using location.reload i am not able display updated data
Use $rootscope like this
Add this $rootScope.$emit("refreshData", {});
instead of Location.reload();
And then add this in your main controller for load data without refresh
var RefreshValue = $rootScope.$on("refreshData", function () {
GetValueMethod(); // call your method (List of object) for get data without reload form
});
$scope.$on('$destroy', RefreshValue);
Don't forget to inject $rootScope.

Howto submit a form with Angular and displaying results on a different page

I'm trying to submit a form from a HTML page using angular.
My HTML code is:
<form role="search">
<input type="text" ng-model="searchSring">
<button type="submit" ng-click="searchPerson(searchString);">Get it!
</button>
</form>
The searchPerson function is calling some PHP page using Ajax and data is successfully retrieved from it.
What I want is when the user has clicked the Get it! button, he should be routed to another HTML page where I would like to display the results. I've tried using "action=" in the form and even calling window.location once Ajax completed to route to the next page. Every time the result is cleared. I've tried using factory with get/set, but this too clears the data on the second page after the window.location call.
Here's the factory code:
myApp.factory('searchService', function(){
var searchService = {};
var mySearchResult = {};
searchService.set = function(searchResult){
mySearchResult = searchResult;
}
searchService.get = function(text){
return mySearchResult;
}
return searchService;
});
CONTROLLER
myApp.controller('OnlineCVController', function($scope, searchService) {
$scope.searchPerson = function(personString) {
$.ajax({
url: "mySearch.php",
type: 'POST',
data: { Person: personString },
async: false, success: function (result) { searchService.set(result);
console.log(result);
window.location = "search.html";
}, error: function (result) { } });
}
Can anyone guide me further?

angular $resource removes a property when object changes

I've created a Service that returns a $resource
module.registerFactory('Website', function ($resource, $cacheFactory) {
var cache = $cacheFactory('websites');
var pagedCache = $cacheFactory('websites_paged');
return $resource('/api/websites/:id', {id: '#id'}, {
query: {method: 'GET', isArray: false, cache: pagedCache},
get: {method: 'GET', cache: cache}
});
});
In an edit state I receive all details by calling
$scope.website = Website.get({'id': $stateParams.id});
The $scope.website promise contains my data as expected. (Below a shortened JSON result from server)
{"id":25,"name":"blabla","url":"http://here.com","description":"blabla",
"tags":[
{"id":6,"name":"..."},
{"id":7,"name":"..."}
{"id":10,"name":"..."}
],
"objectives":[
{"id":3206,"code":"WIS AD3.c","name":"[ommitted objective 3206]","parent_id":3203},
{"id":3209,"code":"WIS AD4.b","name":"[ommitted objective 3209]","parent_id":3207}
]}
My problem is with the objectives property.
In my EditCtrl I open a modal and send the objectives as selected items to the modal. That works perfect.
$scope.selectObjectives = function () {
var modalInstance = $modal.open({
templateUrl: 'app/modules/objectives/templates/select-objectives.html',
controller: 'SelectObjectivesModalCtrl',
size: 'lg',
resolve: {
selectedItems: function () {
return $scope.website.objectives;
}
}
});
modalInstance.result.then(function (selectedItems) {
$scope.website.objectives = selectedItems;
console.log($scope.website);
});
}
When closing the modal the newly selectedItems are injected back into $scope.website.objectives. (cfr. modalInstance.result.then() ... )
The console logs perfectly all properties - including the objectives.
Now comes the weird part:
As soon as I try to access $scope.website in another function (ie update)
The objectives property is removed from $scope.website.
This is my update method:
$scope.updateWebsite = function () {
console.log($scope.website);
$scope.website.$save(function () {
$cacheFactory.get('websites').remove('/api/websites/' + $scope.website.id);
$cacheFactory.get('websites_paged').removeAll();
$state.go('app.websites');
});
};
The console logs all properties in $scope.website - except for the objectives. This is completely removed.
I hope I made myself clear enough.
Thanks for taking some time to help me pointing to the right direction.
My bad.
My response didn't return the entire object as should be in a RESTful POST.

How to remove unwanted databinding in Angularjs

I have an angularjs web page page which allows me to edit some fields. I load the data from my DB, edit it in the page then save the revised data back to the DB. the DB api requires me to submit for amendments the existing DB data and the revised data. Unfortunately when I save the existing data it is binding to the change which I don't want to do !
function providerCtrl($scope, $location, $routeParams, $http)
{
$scope.getProvider = function () {
$http.get(
'/admin/api/'+$routeParams.channel+
'/'+$routeParams.provider).success(function(data){
inputData = data[0];//i want to save this initially but never have it change again, unfortunately its binding with this $scope.settings field changes :-(
$scope.settings = data[0];
});
}
$scope.amendProvider = function (settings) {
console.log($scope.inputData);
var data = {'old': inputData, 'new' : $scope.settings}
console.log(data);
$http({
url: '/admin/api/' + $routeParams.channel + '/' + $routeParams.provider,
method: "PUT",
data: {'old': inputData, 'new' : $scope.settings}
})
.success(function(data){
});
}
$scope.settings = {};
var inputData = {};
$scope.getProvider();
}
when I save the existing data it is binding to the change which I don't want to do !
use angular.copy() utility to clone new instance.
See Documentation HERE

Can you bind data from one scope to update when another changes in angularJS

My web app depends on one specific variable changing throughout the user's visit. It controls what data the user will see at any given time, essentially akin to a TAG.
If the $scope.tagid = 1, is it possible to have another angular model to instantly update its own dataset when tagid is changed to $scop.tagid = 2?
<script >
function PageCtrl($scope) {
$scope.text = '<?=$tagid?>';
}
$scope.showThread = function(tagid) {
$http({method: 'GET', url: 'api/example/thread/id/' + tagid}).
success(function(data, status, headers, config) {
$scope.appDetail = data; //set view model
$scope.view = './Partials/detail.html'; //set to detail view
}).
error(function(data, status, headers, config) {
$scope.appDetail = data || "Request failed";
$scope.status = status;
$scope.view = './Partials/detail.html';
});
}
</script>
<div ng-controller="PageCtrl">
<input ng-model='text' />
<ul>
<li >
<span>{{text}}</span>
</li>
</ul>
</div>
Above is the skeleton of what i'm looking to do.
I realize that if I wanted to, I could call showThread() after each user action and update the data...however, because of the awy I'm looking to set up the site, It makes more sense to only change the tagid, then have everything else update immediately after, rather than picking and choosing each part of the site I want to update. i.e. there may, in addition to showThread(), be updateHeader(), changeSidebar() etc.
Thanks!
I have personally had success using a service; **Assuming that you are using 2 controllers on 1 page, I would create a service like this:
MyApp.app.service("tagDataSvc", function () {
var _tagId = {};
return {
getTagId: function () {
return _tagId;
},
setTagId: function (value) {
_tagId = value;
}
};
});
Next, inject this service into the controllers where this will be used.
In your main controller where you are controlling the TagId (PageCtrl), you would need to set the shared tagId value with a call to the service: tagDataSvc.setTagId($scope.text) You can do this explicitly, or add a $watch on $scope.text, or whatever you prefer.
Finally, in the second controller that you want to automagically update, add a $watch on this service's getTagId() function like so:
$scope.$watch(function () { return tagDataSvc.getTagId(); }, function (newValue, oldValue) {
if (newValue != null) {
$scope.tagId2 = newValue;
//reload whatever needs updating here
}
}, true);

Resources