Angular Restangular on sortable, how to save? - angularjs

I need to change the order of scope, save but me back an error that save() is not a function.
I'm using restangular to create the objects.
The function is triggered Onsort, I tried using http, but also gives me error.
$scope.onChange = function() {
ApiRestangular.all($scope.section).getList($scope.query).then(function(res){
$scope.items = res;
order = ApiRestangular.copy(res);
console.log(order);
$scope.sortOptions = {
animation : 150,
onSort: function(){
order.put().then(function(){
toast.msgToast($scope.section+ ' ...Ordem atualizada!');
});
}
};
});
};

Related

Refreshing FullCalendar upon saving events with Angular Resource $save

I'm building a calendar inspired by this example http://plnkr.co/edit/pIDltQRV6TQGD4KQYnj7?p=preview and adding $save to add new events using RESTful server connection.
I'm trying to find a way to make the calendar show the new events when they are $saved without manually refreshing the browser.
My attempt to get this to work was to add (or remove) the event data to the event array (gDataService.events). Although it does change the content of the array, the change is not shown in the calendar. (e.g., if I change the date of the event, the event won't move to the new date.)
Can someone point me in the right direction? Thanks!
HTML
<div ui-calendar="uiConfig.calendar" class="span8 calendar" ng-model="eventSources"></div>
Controller1 ... This saves new event.
$scope.ok = function () {
$scope.entry = new calFactory();
$scope.entry.data = data
$scope.entry.$save( function(){
// data saved. do something here.
toaster.pop('success','Message','Update successfully completed.');
});
};
Controller2 ... Main controller that defines eventSource
myApp.controller("MainCtrl", function($scope,$compile,uiCalendarConfig, calFactory,eventFactory, gDataService) {
gDataService.events = function(start, end, callback) {
var d = new Date(start);
var events;
events = calFactory.query({
start: start,
end: end
});
events.$promise.then(function(value){
gDataService.events = events;
//have to call the callback as well to keep the calendar happy
callback(gDataService.events);
$scope.statusTxt = $scope.statusTxt + " ... Event loading completed at " + moment(new Date()).format("HH:mm:ss");
}
);
};
/* event sources array*/
$scope.eventSources = [gDataService.events]; /*, $scope.eventSource, $scope.eventsF*/
})
Factory
myApp.factory("calFactory",['$resource','$filter', function($resource, $filter) {
return $resource("/griddata/", {}, {
get: {
method: 'GET'
},
save: {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'},
transformRequest: function(data, headersGetter) {
data = angular.toJson(data);
data = $.parseJSON(data);
return $.param(data.data);
}
}
});
}]);
gDataService ... This stores event data and make it available to other parts of the program
myApp.factory("gDataService", function ($rootScope, calFactory) {
var service = {};
service.events = [];
service.addData = function(object, no_broadcast) {
this.events.push({
__id: object.task_id, title: object.task, start: object.duedates,
backgroundColor: bColor, textColor: bTextColor, borderColor: bColor
});
if (!no_broadcast) {$rootScope.$broadcast("gDataUpdated")};
};
service.removeData = function(task_id, no_broadcast) {
var arr_index = _.findIndex(this.events, {'__id': task_id});
this.events.splice(arr_index, 1);
if (!no_broadcast) {$rootScope.$broadcast("gDataUpdated")};
};
return service;
});
Nobody would answer to this much sophisticated question.
You have some typos:
Missed closing with ";", "]"...
What's inside 'function calFactory'? What is '$broadcast'?
Why do you put '$' leading the JavaScript object? Is this meaning "private var"?
"if (!no_broadcast) ..." is not coding, but commenting.
In "$scope.entry.$save( function(){",
Why entry doesn't have '$', but scope and save have it?
Here is the answer from chris-rock https://github.com/angular-ui/ui-calendar/issues/200.
Changed scope.init in calendar.js like this:
scope.init = function(){
calendar.fullCalendar(options);
window.calendar = calendar; /// This is the key
};
Now I can add or remove events dynamically using window.calendar.fullCalendar('removeEvents' or 'renderEvent')!!
Here is how I changed my code.
gDataService
service.addData = function(object, no_broadcast) {
//add additional project
this.added_event = {
__id: object.task_id, title: object.task, start: object.duedates,
backgroundColor: bColor, textColor: bTextColor, borderColor: bColor
};
this.events.push(this.added_event);
if (!no_broadcast) {$rootScope.$broadcast("gDataUpdated")};
};
service.removeData = function(_id, no_broadcast) {
var arr_index = _.findIndex(this.events, {'_id': _id});
this.delete_id = _id;
this.events.splice(arr_index, 1);
if (!no_broadcast) {$rootScope.$broadcast("gDataUpdated")};
};
return service;
Controller
$scope.$on('gDataUpdated', function(){
if (gDataService.delete_id) {
window.calendar.fullCalendar('removeEvents',gDataService.delete_id); // This removes this event from the calendar
gDataService.delete_id = null;
};
if (gDataService.added_event) {
window.calendar.fullCalendar('renderEvent',gDataService.added_event,false); // This adds this event to the calendar
gDataService.added_event = null;
};

Angular.js, $resource, how to manage multiple asynchronous requests

I am implementing a "copy on write" CRUD system meaning i never overwrite a database entry but mark as inactive and write a new record. When editing an existing record this means i write to the old record deactivating then create a new record. My controller code is below:
$scope.save = function() {
if(!$scope.newDevice){
var editDevice = $scope.device;
$scope.delete(editDevice);
$scope.device = {name: editDevice.name, type: editDevice.type, hash: editDevice.hash};
}
var newDevice = new DeviceService($scope.device);
newDevice = newDevice.$save(function(newDevice, putResponseHeaders) {
DeviceService.query({active : true}, function(devices){
$scope.devices = devices;
});
});
};
When i call to get the list of active devices with DeviceService.query({active : true} I still get the old record as active since it executes and returns before the delete method has been processed and returned.
I think i should be using promise maybe. How do i write this code to be better and work?
thanks
Yes, you want to use promises. You have two options:
Use the success/failure callbacks that all $resource methods supply. Note you're using this when you call $save. You could do the same when you call $delete on the resource, so that your remaining code only executes when the $delete() succeeds. These callbacks are automatically invoked when the $resource's built-in promise is resolved or rejected.
Make your $scope.delete() function return a promise. It sounds like this might be better, because you do not always want to make the delete request.
The code for #2 might look like this:
// this function use the '$q' service, which you need to inject
// in your controller
$scope.delete = function(item) {
var deferred = $q.defer();
item.$delete({},
function(response) {
// the delete succeeded, resolve the promise
deferred.resolve(response);
},
function(error) {
// failed, reject the promise
deferred.reject(error);
}
);
return deferred.promise;
}
$scope.save = function() {
if(!$scope.newDevice){
var editDevice = $scope.device;
$scope.delete(editDevice).then(function(response) {
$scope.device = {name: editDevice.name, type: editDevice.type, hash: editDevice.hash};
// now trigger the code to save the new device (or whatever)
$scope.doTheActualSave();
},
function(error) { });
} else {
// there was nothing to delete, just trigger the code to save
$scope.doTheActualSave();
}
};
$scope.doTheActualSave = function() {
var newDevice = new DeviceService($scope.device);
newDevice = newDevice.$save(function(newDevice, putResponseHeaders) {
DeviceService.query({active : true}, function(devices){
$scope.devices = devices;
});
});
}

WebSQL data into AngularJs DropDown

I have very simple question about getting data from WebSql
I have DropDown i.e
<select id="selectCatagoryFood" data-role="listview" data-native-menu="true"
ng-init="foodCatagory = foodCatagories.cast[0]"
ng-options="foodCatagory as foodCatagory.text for foodCatagory in foodCatagories.cast"
ng-model="foodCatagory"
ng-change="changeFoodCatagory()">
</select>
now i want to add data init from webSQL. I already get Data from webSql but i am confuse that how to add that data into DropDown
An example or hints maybe very helpful for me.
Update 1 :: Add Controller Code
myApp.controller('foodSelection',function($scope,foodCatagories){
$scope.foodCatagories = foodCatagories;
$scope.changeFoodCatagory = function(){
alert($scope.foodCatagory.value);
}
});
Update 2 webSQL and JayData
_context.onReady({
success: showData,
error: function (error){
console.log(error);
}
});
function showData(){
var option = '';
_context.FoodGroup.forEach(function(FG)
{
option += '<option value="'+FG.FoodGroupID+'">'+FG.Description+'</option>';
}).then(function(){
console.log(option);
});
}
Update 3
var myApp = angular.module('myApp',[]);
myApp.factory('foodCatagories',function(){
var foodCatagories = {};
foodCatagories.cast = [
{
value: "000",
text: "Select Any"
}
];
return foodCatagories;
});
Update 4
One thing that i didn't mention is that I am using JayData for getting data from webSQL to my App
I will try to explain how it works:
EDIT: Live demo
html
Here is your stripped down select.
<select ng-options="item as item.text for item in foodCategories"
ng-model="foodCategory"
ng-required="true"
ng-change="changeFoodCategory()">
</select>
The directive ng-options will fill automatically the option elements in your select. It will take the foodCategories variable from the $scope of your controller and foreach item in the collection, it will use the text property as the label shown (<option>{{item.text}}</option>') and it will select the whole objectitemas the value of the selectedoption. You could also refer to a property as the value like ({{item.text}}). Then yourng-modelwould be set to theid` value of the selected option.
The directive ng-model corresponds to the variable in the $scope of your controller that will hold the value of the selected option.
The directive ng-required allows you to check if a value has been selected. If you are using a form, you can check if the field is valid formName.ngModelName.$valid. See the docs for more details on form validation.
The directive ng-change allows you to execute a function whenever the selected option changes. You may want to pass the ng-model variable to this function as a parameter or call the variable through the $scope inside the controller.
If no default value is set, angular will add an empty option which will be removed when an option is selected.
You did use the ng-init directive to select the first option, but know that you could set the ng-model variable in your controller to the default value you would like or none.
js
Here I tried to simulate your database service by returning a promise in the case that you are doing an async request. I used the $q service to create a promise and $timeout to fake a call to the database.
myApp.factory('DbFoodCategories', function($q, $timeout) {
var foodCategories = [
{ id: 1, text: "Veggies", value: 100 },
{ id: 2, text: "Fruits", value: 50 },
{ id: 3, text: "Pasta", value: 200 },
{ id: 4, text: "Cereals", value: 250 },
{ id: 5, text: "Milk", value: 150 }
];
return {
get: function() {
var deferred = $q.defer();
// Your call to the database in place of the $timeout
$timeout(function() {
var chance = Math.random() > 0.25;
if (chance) {
// if the call is successfull, return data to controller
deferred.resolve(foodCategories);
}
else {
// if the call failed, return an error message
deferred.reject("Error");
}
}, 500);
/* // your code
_context.onReady({
success: function() {
deferred.resolve(_contect.FoodGroup);
},
error: function (error){
deferred.reject("Error");
}
});
*/
// return a promise that we will send a result soon back to the controller, but not now
return deferred.promise;
},
insert: function(item) {
/* ... */
},
update: function(item) {
/* ... */
},
remove: function(item) {
/* ... */
}
};
});
In your controller you set the variables that will be used in your view. So you can call your DbFoodCategories service to load the data into $scope.foodCategories, and set a default value in $scope.foodCategory that will be used to set the selected option.
myApp.controller('FoodSelection',function($scope, DbFoodCategories){
DbFoodCategories.get().then(
// the callback if the request was successfull
function (response) {
$scope.foodCategories = response; //response is the data we sent from the service
},
// the callback if an error occured
function (response) {
// response is the error message we set in the service
// do something like display the message
}
);
// $scope.foodCategory = defaultValue;
$scope.changeFoodCategory = function() {
alert($scope.foodCatagory.value);
}
});
I hope that this helped you understand more in detail what is happening!
See this example and how use $apply to update the data in scope.
in the new version we released a new module to support AngularJS. We've started to document how to use it, you can find the first blogpost here
With this you should be able to create your dropdown easily, no need to create the options manually. Something like this should do the trick:
myApp.controller('foodSelection',function($scope, $data) {
$scope.foodCatagories = [];
...
_context.onReady()
.then(function() {
$scope.foodCatagories = _context.FoodGroup.toLiveArray();
});
});
provided that FoodGroup has the right fields, of course

Angular resource (ngResource) won't make the AJAX call when called inside a function

I'm trying to make an AJAX call with ngResource, In the code below 'a' and 'b' both print, but the AJAX call from Table.import() does not get made. If I move the AJAX call outside of onFileRead, then it works. What could be the problem?
var TableImportController = ['$scope','Table', 'project', 'table',
function($scope, Table, project, table) {
$scope.table = table;
$scope.project = project;
$scope.onFileRead = function(file) {
console.log('a');
Table.import({ data : file.data}, function() {
}, function() {
});
console.log('b');
};
}];
Where Table is an ngResource
.factory('Table', function($resource) {
var Table = $resource('/api/tables/:id:listAction/:itemAction',
{
id: '#id',
listAction: '#listAction',
itemAction: '#itemAction'
},
{
update: { method: 'PUT' },
import : { method: 'POST', params: { listAction: 'import' }},
}
);
return Table;
});
You are declaring $scope.onFileRead as a function.
What is calling onFileRead?
When you move the call outside of the function, it is being run as part of initialization.
What provides the input file?
Probably bind to the onFileRead function from something in your DOM.
I figured it out. It looks like I ran into this bug: https://github.com/angular/angular.js/issues/2794#issuecomment-18807158.
I solved the issue by wrapping the AJAX call (and eventually moved it to where the onFileRead callback is triggered) in a scope.$apply(function() { });

Can't get waiting for function to return (with promises?) working in angular controller

I'm trying to get the following findTimelineEntries function inside an Angular controller executing after saveInterview finishes:
$scope.saveInterview = function() {
$scope.interviewForm.$save({employeeId: $scope.employeeId}, function() {
$scope.findTimelineEntries();
});
};
The save action adds or edits data that also is part of the timeline entries and therefore I want the updated timeline entries to be shown.
First I tried changing it to this:
$scope.saveInterview = function() {
var functionReturned = $scope.interviewForm.$save({employeeId: $scope.employeeId});
if (functionReturned) {
$scope.findTimelineEntries();
}
};
Later to this:
$scope.saveInterview = function() {
$scope.interviewForm.$save({employeeId: $scope.employeeId});
};
$scope.saveInterview.done(function(result) {
$scope.findTimelineEntries();
});
And finaly I found some info about promises so I tried this:
$scope.saveInterview = function() {
$scope.interviewForm.$save({employeeId: $scope.employeeId});
};
var promise = $scope.saveInterview();
promise.done(function() {
$scope.findTimelineEntries();
});
But somehow the fact that it does work this way according to http://nurkiewicz.blogspot.nl/2013/03/promises-and-deferred-objects-in-jquery.html, doesn't mean that I can use the same method on those $scope.someFuntcion = function() functions :-S
Here is a sample using promises. First you'll need to include $q to your controller.
$scope.saveInterview = function() {
var d = $q.defer();
// do something that probably has a callback.
$scope.interviewForm.$save({employeeId: $scope.employeeId}).then(function(data) {
d.resolve(data); // assuming data is something you want to return. It could be true or anything you want.
});
return d.promise;
}

Resources