Laravel 5 TokenMismatch on Backbone.js destroy method, with _token set - backbone.js

I am trying to delete a model via:
var FeaturedUsersView = Backbone.View.extend({
events: {
"click .remove-featured-user" : "removeFeaturedUser"
},
template : _.template(FeaturedUsersTemplate),
render: function(){
this.$el.html(this.template({ featuredUsers: App.featuredUsers.toJSON() }));
return this;
},
removeFeaturedUser: function(event) {
userToRemove = this.collection.get(event.target.id);
userToRemove.set("_token", $('input[name="_token"]').val());
userToRemove.destroy({
wait: true,
/*
*headers: {
* _token : $('input[name="_token"]').val()
*},
*async: false,
*/
url: '/api/admin/versions/' + App.config.get("class_id") + '/featured_users',
});
}
});
I keep getting a ERROR: exception 'Illuminate\Session\TokenMismatchException'.
This same view have a model.save() that works with the same token. I have a feeling the destroy method is ignoring the token in the DELETE request. Any tips?
Here is backbone.js's destroy method:
destroy: function(options) {
options = options ? _.clone(options) : {};
var model = this;
var success = options.success;
var wait = options.wait;
var destroy = function() {
model.stopListening();
model.trigger('destroy', model, model.collection, options);
};
options.success = function(resp) {
if (wait) destroy();
if (success) success.call(options.context, model, resp, options);
if (!model.isNew()) model.trigger('sync', model, resp, options);
};
var xhr = false;
if (this.isNew()) {
_.defer(options.success);
} else {
wrapError(this, options);
xhr = this.sync('delete', this, options);
}
if (!wait) destroy();
return xhr;
},

Adding this globally fixed my problem:
<meta name="csrf-token" content="{{ csrf_token() }}">
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});

Related

$cordovaFileTransfer can not work

use $cordovaFileTransfer to upload images,but it stop at 99%, $_FILES is empty in PHP;
and i get evt object.
{"bubbles":"false","cancelBubble":"false","cancelable":"false","lengthComputable":"true","loaded":"16656","total":"491176"}
{"bubbles":"false","cancelBubble":"false","cancelable":"false","lengthComputable":"true","loaded":"33040","total":"491176"}
{"bubbles":"false","cancelBubble":"false","cancelable":"false","lengthComputable":"true","loaded":"98576","total":"491176"}
{"bubbles":"false","cancelBubble":"false","cancelable":"false","lengthComputable":"true","loaded":"131344","total":"491176"}
{"bubbles":"false","cancelBubble":"false","cancelable":"false","lengthComputable":"true","loaded":"147728","total":"491176"}
{"bubbles":"false","cancelBubble":"false","cancelable":"false","lengthComputable":"true","loaded":"164112","total":"491176"}
{"bubbles":"false","cancelBubble":"false","cancelable":"false","lengthComputable":"true","loaded":"180496","total":"491176"}
{"bubbles":"false","cancelBubble":"false","cancelable":"false","lengthComputable":"true","loaded":"213264","total":"491176"}
{"bubbles":"false","cancelBubble":"false","cancelable":"false","lengthComputable":"true","loaded":"229648","total":"491176"}
{"bubbles":"false","cancelBubble":"false","cancelable":"false","lengthComputable":"true","loaded":"65808","total":"491176"}
{"bubbles":"false","cancelBubble":"false","cancelable":"false","lengthComputable":"true","loaded":"82192","total":"491176"}
{"bubbles":"false","cancelBubble":"false","cancelable":"false","lengthComputable":"true","loaded":"114960","total":"491176"}
{"bubbles":"false","cancelBubble":"false","cancelable":"false","lengthComputable":"true","loaded":"295184","total":"491176"}
{"bubbles":"false","cancelBubble":"false","cancelable":"false","lengthComputable":"true","loaded":"262416","total":"491176"}
{"bubbles":"false","cancelBubble":"false","cancelable":"false","lengthComputable":"true","loaded":"311568","total":"491176"}
{"bubbles":"false","cancelBubble":"false","cancelable":"false","lengthComputable":"true","loaded":"327952","total":"491176"}
{"bubbles":"false","cancelBubble":"false","cancelable":"false","lengthComputable":"true","loaded":"344336","total":"491176"}
{"bubbles":"false","cancelBubble":"false","cancelable":"false","lengthComputable":"true","loaded":"360720","total":"491176"}
{"bubbles":"false","cancelBubble":"false","cancelable":"false","lengthComputable":"true","loaded":"377104","total":"491176"}
{"bubbles":"false","cancelBubble":"false","cancelable":"false","lengthComputable":"true","loaded":"409872","total":"491176"}
{"bubbles":"false","cancelBubble":"false","cancelable":"false","lengthComputable":"true","loaded":"442640","total":"491176"}
{"bubbles":"false","cancelBubble":"false","cancelable":"false","lengthComputable":"true","loaded":"393488","total":"491176"}
{"bubbles":"false","cancelBubble":"false","cancelable":"false","lengthComputable":"true","loaded":"426256","total":"491176"}
{"bubbles":"false","cancelBubble":"false","cancelable":"false","lengthComputable":"true","loaded":"459024","total":"491176"}
{"bubbles":"false","cancelBubble":"false","cancelable":"false","lengthComputable":"true","loaded":"475408","total":"491176"}
{"bubbles":"false","cancelBubble":"false","cancelable":"false","lengthComputable":"true","loaded":"491163","total":"491176"}
{"bubbles":"false","cancelBubble":"false","cancelable":"false","lengthComputable":"true","loaded":"196880","total":"491176"}
{"bubbles":"false","cancelBubble":"false","cancelable":"false","lengthComputable":"true","loaded":"246032","total":"491176"}
what's wrong with the property loaded;why it increase repeatly;
upload code
$scope.upload = function(imageURI) {
$scope.dangerList[$scope.setting.num][$scope.setting.imageType + '1pic'] = imageURI;
var server = 'http://localhost/test.php';
var dirName = 'check';
var desName = 'test';
var options = {
'httpMethod': 'POST',
'params': {
'dirName': dirName,
'desName': desName
}
};
var promise = $cordovaFileTransfer.upload(server, imageURI, options, true);
promise.then(function(data) {
console.log(data);
}, function(data) {}, function(evt) {
$ionicLoading.show({
template: '<p>upload:' + parseInt(100.0 * evt.loaded / evt.total) + '%</p>',
//duration: 1000,
});
});
return promise;
};
and ngCordova\src\plugins\fileTransfer.js
angular.module('ngCordova.plugins.fileTransfer', [])
.factory('$cordovaFileTransfer', ['$q', '$timeout', function($q, $timeout) {
return {
download: function(source, filePath, options, trustAllHosts) {
var q = $q.defer();
var ft = new FileTransfer();
var uri = (options && options.encodeURI === false) ? source : encodeURI(source);
if (options && options.timeout !== undefined && options.timeout !== null) {
$timeout(function() {
ft.abort();
}, options.timeout);
options.timeout = null;
}
ft.onprogress = function(progress) {
q.notify(progress);
};
q.promise.abort = function() {
ft.abort();
};
ft.download(uri, filePath, q.resolve, q.reject, trustAllHosts, options);
return q.promise;
},
upload: function(server, filePath, options, trustAllHosts) {
var q = $q.defer();
var ft = new FileTransfer();
var uri = (options && options.encodeURI === false) ? server : encodeURI(server);
if (options && options.timeout !== undefined && options.timeout !== null) {
$timeout(function() {
ft.abort();
}, options.timeout);
options.timeout = null;
}
ft.onprogress = function(progress) {
q.notify(progress);
};
q.promise.abort = function() {
ft.abort();
};
ft.upload(filePath, uri, q.resolve, q.reject, options, trustAllHosts);
return q.promise;
}
};
}]);
and push interceptor
.factory('UserInterceptor', function ($q, $rootScope) {
return {
request:function(config){
config.headers = config.headers || {};
config.headers.UID = $rootScope.user.id || 0;
return config;
},
requestError: function(err){
return $q.reject(err);
},
response: function (response) {
return response;
},
};
})
it could work few days ago.
during the time,
add plaform with android#5.1.1 instead of android#4.1.1;
update cordova;
use ionic 1.7.3 now;
and here is the download code,it can works,but will download file twice
$scope.down = function(fname) {
var fileTransfer = new FileTransfer();
var uri = encodeURI($rootScope.rootUrl + fname);
var fileURL = cordova.file.externalRootDirectory + fname;
fileTransfer.download(
uri,
fileURL,
function(entry) {
console.log(entry);
},
function(error) {
console.log(error);
},
false, {
headers: {
"Authorization": "Basic dGVzdHVzZXJuYW1lOnRlc3RwYXNzd29yZA=="
}
}
);
};
This is actually the response from progress event of cordovaFileTransfer.
On success it'll give response something like this:
Object {bytesSent: 3228135, responseCode: 200, response: "<!-- Served from 80.251.0.59 / test.talia.net, as …imited↵</p>↵↵</td></tr></table>↵↵</body>↵</html>↵", objectId: ""}
But as per the output you are getting,I think the function is getting interrupted by the same method from another instance because your whole file was almost uploaded in the 3rd last line.
"cancelable":"false","lengthComputable":"true","loaded":"491163","total":"491176"}
And then it picked up from some another point.
Please provide the code so I can try to assist you further.
Thank you

How to delete file in dropzone?

init: function() {
dzClosure = this;
document.getElementById("place-order").addEventListener("click", function(e) {
e.preventDefault();
e.stopPropagation();
dzClosure.processQueue();
});
this.on("sendingmultiple", function(data, xhr, formData) {
formData.append("key", $scope.formData.order_id);
});
this.on('success', function(file, resp) {
console.log(resp); //result - {error:false, file_id:10}
file_ids.push(resp.file_id);
});
},
removedfile: function(file) {
console.log(file_ids);
x = confirm('Do you want to delete?');
if (!x) return false;
var name = file.name;
$.ajax({
type: 'POST',
url: 'orders/fileDelete.php',
data: {"file_id": file_ids},
dataType: 'json'
});
var _ref;
return (_ref = file.previewElement) != null ? _ref.parentNode.removeChild(file.previewElement) : void 0;
}
Above my code working fine. But I want to delete my mysql row while clicking on the "Remove" button in dropzone. I am unable to get the current file_id in my removedfile function. Please help me and let me know how I will get resp.file_id in my removedfile function?
You could set an id property to file on success event, then on removal just get it as file.id. Hope this helps you.
init: function() {
dzClosure = this;
document.getElementById("place-order").addEventListener("click", function(e) {
e.preventDefault();
e.stopPropagation();
dzClosure.processQueue();
});
this.on("sendingmultiple", function(data, xhr, formData) {
formData.append("key", $scope.formData.order_id);
});
this.on('success', function(file, resp) {
file.id = resp.file_id;
});
},
removedfile: function(file) {
x = confirm('Do you want to delete?');
if (!x) return false;
//send delete to backend only if file was uploaded.
//Dropzone will cancel requests in progress itself.
if(file.id) {
$.ajax({
type: 'POST',
url: 'orders/fileDelete.php',
data: {"file_id": file.id},
dataType: 'json'
});
}
}
After lots of research I found where was error in my code.
Actually my ajax responded JSON. But here is dropzone.js not getting json data. So I have converted my dynamic String data to JSON format.
Code:
this.on('success', function(file, resp) {
console.log(resp); // result - {error:false, file_id:10}
var response = JSON.parse(resp);
file.file_id = response.file_id;
});

angular then catch success error from services

I'm afraid I may have gone down the rabbit hole of recursive promises.
I have a service that handles my api. (It's got an extra layer of promise so that I could switch back to a local json if the api went offline. (Not sure how necessary it is anymore) - mayte I should eliminate it for simplicity).
Then I've got the promised async call in my controller.
This all works great as long as I get the data I expect, but it doesn't handle errors very well. When I get 400's and 500's, it doesn't send the error message to the user via toastr.
Sadly, this is not a fully-compliant RESTful api. The 400 error I get back is simply
{"Message":"No packages found"}
I don't really get how to get this to behave as it should, and replace success/error with then/catch (as per Angular best practice).
Here is a typical service call:
var _getPackagesPage = function (options) {
var pageSize = options.data.pageSize;
var page = options.data.page -1;
return $q (function(resolve, reject) {
switch (dataSource) {
case 'api'://staging - live api data
return $http({
method: 'get',
url: serviceBase + 'api/Packages?pageSize=' + pageSize + '&page=' + page
}).then(function(results) {
resolve(results);
});
break;
default: // dev - local json
$.getJSON('Content/data/Packages.json', function (json) {
var pageSize = options.data.pageSize;
var page = options.data.page;
var newjson = json.splice(page*pageSize,pageSize);
resolve(newjson);
});
}
});
};
and a typical call in a controller:
(options is the data object handed back to my data grid (Kendo))
vm.getPackages = function(options) {
return packagesService.getPackagesPage (options)
.then(function(results) {
options.success(results.data.Items);
})
.catch(function(error) {
options.error(error);
toastr.error(error.Message);
});
};
How can I clean this up?
[ UPDATE ] Attempted fix per Answer 1, below
Service:
var _getOrdersPage = function (options) {
var deff = $q.defer();
var pageSize = options.data.pageSize;
var page = options.data.page -1;
return $http({
method: 'get',
url: serviceBase + 'api/Packages?pageSize=' + pageSize + '&page=' + page
})
.then(
function(results) {
deff.resolve(results);
},
function(ex){
deff.reject(ex);
});
return deff.promise;
};
Controller:
vm.getOrders = function (options) {
return ordersService.getOrdersPage (options)
.then(function(results) {
console.log("results!");
console.log(results);
})
.catch(function(error) {
console.log("error!");
console.log(error);
});
};
results in:
GET http://< myURL >/api/Packages?pageSize=20&page=0 400 (Bad Request)
results!
undefined
I'm removing the switch case for brevity.
var _getPackagesPage = function (options) {
var pageSize = options.data.pageSize;
var page = options.data.page -1;
var deff = $q.defer();
$http({
method: 'get',
url: serviceBase + 'api/Packages?pageSize=' + pageSize + '&page=' + page
}).then(
function(results) {
deff.resolve(results);
},
function(ex){
deff.reject(ex);
});
return deff.promise;
};
Controller
vm.getOrders = function (options) {
return ordersService.getOrdersPage (options)
.then(
function(results) {
console.log("results!");
console.log(results);
},
function(error) {
console.log("error!");
console.log(error);
});
};
If you dont have any logic inside your service, then you could return the $http itself as $http inturn is a promise:
var _getPackagesPage = function (options) {
var pageSize = options.data.pageSize;
var page = options.data.page -1;
return $http({
method: 'get',
url: serviceBase + 'api/Packages?pageSize=' + pageSize + '&page=' + page
});
};
You have too many returns in your service. The second one is not called.
You don't need to create a promise manually since $http returns apromise.
You're not returning data from your service.
var _getOrdersPage = function(options) {
var pageSize = options.data.pageSize;
var page = options.data.page -1;
return $http({
method: 'get',
url: serviceBase + 'api/Packages?pageSize=' + pageSize + '&page=' + page
})
.then(
function(results) {
return results;
},
function(ex){
return ex;
});
}
Your controller is fine, you can use catch() or pass an error callback.
Example:
function myService($http) {
this.getData = function(url) {
return $http.get(url).
then(function(response) {
return response.data;
}, function(error) {
return error;
});
}
};
function MyController(myService) {
var vm = this;
vm.result = [];
vm.apiUrl = "https://randomuser.me/api/";
myService.getData(vm.apiUrl).then(function (data) {
vm.result = data;
},
function(error) {
console.log(error);
});
};
angular.module('myApp', []);
angular
.module('myApp')
.service('myService', myService)
.controller('MyController', MyController);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="MyController as ctrl">
{{ ctrl.result }}
</div>
</div>

Angular resolve promise and update existing scope

I am trying to understand Angular's promises and scopes. Actually I implemented the directive bellow. The thing that I want to do is to receive images from server and store locally in order to cache them for next times. Also I want to show a spinner before the load of image is completed and show it after the completion.
How can update variable newUrl into directive when completed all of these promises?
Do you have any idea?
My HTML code is:
<div style="text-align: center;"
cache-src
url="https://upload.wikimedia.org/wikipedia/commons/c/c0/Aix_galericulata_(Male),_Richmond_Park,_UK_-_May_2013.jpg">
</div>
My directive is:
.directive('cacheSrc', [function () {
return {
restrict: 'A',
scope: {
url: '#'
},
controller: 'cacheSrcCtrl',
template: '<img width="100%" ng-if="newUrl!=null" src="{{newUrl}}"><ion-spinner ng-if="newUrl==null" icon="spiral"></ion-spinner>',
};
}])
And the controller of directive has the function bellow:
document.addEventListener('deviceready', function () {
$scope.updateUrl = function (newUrl) {
$scope.newUrl = newUrl;
};
var tmp = $scope.url;
$cordovaSQLite.execute(db, 'SELECT * FROM images where url = (?)', [tmp])
.then(function (result) {
if (result.rows.length > 0) {
$scope.exists = true;
for (var i = 0; i < res.rows.length; i++) {
var image = {
id: res.rows.item(i).id,
url: res.rows.item(i).url,
uri: res.rows.item(i).uri
};
$scope.updateUrl(image.uri);
}
} else {
$scope.exists = false;
var fileTransfer = new FileTransfer();
var uri = encodeURI(tmp);
var uriSave = '';
var fileURL = cordova.file.dataDirectory + uri;//'kaloudiaImages';// + getUUID();// + "DCIM/myFile";
fileTransfer.download(
uri, fileURL, function (entry) {
uriSave = entry.toURL();
KaloudiaDB.add(tmp, fileURL);
$scope.newUrl = fileURL;
$scope.updateUrl(fileURL);
},
function (error) {
console.log("download error code" + error.code);
},
false, {
headers: {
// "Authorization": "Basic dGVzdHVzZXJuYW1lOnRlc3RwYXNzd29yZA=="
}
}
).then(function (data) {
$scope.newUrl = fileURL;
});
}
}, function (error) {
$scope.statusMessage = "Error on saving: " + error.message;
})
.then(function (data) {
$scope.$apply(function () {
$scope.newUrl = fileURL;
});
});
});

why it fails when I declare a function to invoke in controller

It will fail to bind data from http response if you uncomment "//" line,why? It should be the same, right?
var m = angular.module('users', []);
m.controller('UserList', function($scope) {
// $scope.getdata = function() {
var u = "http://wisebe.duapp.com/admin?queryusers";
var userList = this;
var body = {
activityid: "10",
checkin: $('#checkin').val()
};
$.ajax({
url: u,
type: "post",
async: false,
data: body,
success: function(data) {
userList.users = data;
}
});
// };
// $scope.getdata();
$('#checkin').change(function() {
// $scope.$apply();
});
});

Resources