I'm trying to update data on backbone.But my save() function post insead of put.
editEvent:function(e){
var departments=new Department();
departments.set("departmentName",this.$el.find(".departmentName").val());
departments.save();
this.render();
},
departmentModel
var Department = Backbone.Model.extend({
urlRoot: "/rest/department",
idAttribute:'departmentID'
}
});
return Department;
template
<th>
<span>{{user.department.departmentName}}</span>
<input data-placement="top" title="Boş geçilemez!" class="form-control text-center departmentName" type='text'
style='display: none;' value='{{user.department.departmentName}}'/>
</th>
That's by design, here's a snippet from the Backbone docs for the save function:
If the model isNew, the save will be a "create" (HTTP POST), if the
model already exists on the server, the save will be an "update" (HTTP
PUT).
Model is considered 'New' if it does not have an id.
Since you're creating the model for the first time, Backbone will use the POST method as it should, because it means you're creating a new resource. For more info on the meaning of HTTP verbs.
My suggestion would be solving this on the server side and making separate handlers for POST and PUT, but if you really want to force PUT method, here are some tips: What is the least ugly way to force Backbone.sync updates to use POST instead of PUT?
I solved the problem with using id.If you try PUT request without id,backbone think "it's a new model".But you save with data's id value, backbone think PUT request.
That's why i tried put request with id and that's worked.
departments.set("departmentID",this.$el.find(".departmentName").data("id"));
departments.set("departmentName",this.$el.find(".departmentName").val());
departments.save();
Related
I would like to setup axios to delete a record using a resource route:
axios.delete('/job-management', this.deletedata).then((res)=>{
console.log(res);
})
For my routes I have:
Route::resource('job-management', "PositionsController", [ 'as' => 'jobs']);
Now, in my PositionsController I have:
public function destroy(Positions $positions) {
return $positions;
}
But the above always returns "method not allowed". How can I handle a delete request with the axios delete() method?
Laravel throws the MethodNotAllowedHttpException when we attempt to send a request to a route using an HTTP verb that the route doesn't support. In the case of this question, we see this error because the JavaScript code sends a DELETE request to a URL with the path of /job‑management, which is handled by a route that only supports GET and POST requests. We need to change the URL to the conventional format Laravel expects for resourceful controllers.
The error is confusing because it hides the fact that we're sending the request to the wrong URL. To understand why, let's take a look at the routes created by Route::resource() (from the documentation):
Verb URI Action Route Name
GET /job-management index job-management.index
GET /job-management/create create job-management.create
POST /job-management store job-management.store
GET /job-management/{position} show job-management.show
GET /job-management/{position}/edit edit job-management.edit
PUT/PATCH /job-management/{position} update job-management.update
DELETE /job-management/{position} destroy job-management.destroy
As shown above, URLs with a path component of /job-management are passed to the controller's index() and store() methods which don't handle DELETE requests. This is why we see the exception.
To perform a DELETE request as shown in the question, we need to send the request to a URL with a path like /job-management/{position}, where {position} is the ID of the position model we want to delete. The JavaScript code might look something like:
axios.delete('/job-management/5', this.deletedata).then((res) => { ... })
I've hardcoded the position ID into the URL to clearly illustrate the concept. However, we likely want to use a variable for the this ID:
let positionId = // get the position ID somehow
axios.delete(`/job-management/${positionId}`, this.deletedata).then((res) => { ... })
The URL in this form enables Laravel to route the DELETE request to the controller's destroy() method. The example above uses ES6 template string literals because the code in the question suggests that we're using a version of JavaScript that supports this feature. Note the placement of backticks (`) around the template string instead of standard quotation marks.
as I can see in your code above, you pass Positionseloquent as a parameter to destroy method but in your vueJS you don't pass this object. for that you would pass it like this :
axios.delete('/job-management/${id}').then((res)=>{
console.log(res);
})
and the id param inside the url of ur axios delete, it can object of data or any think.
i hope this help you
I need to make a POST to a server-side API. I must send an id key into the request body to the server.
I use a Backbone model. But when I do:
myModel.set("id", somevalue)
myModel.save()
The network request that is fired is : URL/someValue [PUT]
Backbones doesn't do a POST but a PUT and appends the id to the url.
So I just want to pass an id key to the server without Backbone noticing.
From Backbone's doc:
Backbone is pre-configured to sync with a RESTful API.
[...]
The default sync handler maps CRUD to REST like so:
create → POST /collection
read → GET /collection[/id]
update → PUT /collection/id
patch → PATCH /collection/id
delete → DELETE /collection/id
A new entry doesn't have an ID, so if you give an ID to the model before saving it, Backbone defaults to a PUT request because it thinks you want to save an existing entry.
How to make a POST request with an id?
Choose one of the following solutions.
Stick to a RESTful API
This one is the obvious one. If you can, stick to the standard.
Change the API to handle PUT/PATCH requests and only use POST on creation. Make the API endpoint take the ID from the URL.
RESTful API best practices
Pass the type option1
Simple and works really well for a one-off situation.
Every options passed to save (or fetch) overrides the options the sync function defines by default and passes to jQuery.ajax function.
Backbone sync source
// Make the request, allowing the user to override any Ajax options.
var xhr = options.xhr = Backbone.ajax(_.extend(params, options));
var url = model.url(); // get the url before setting the `id`
model.save({
id: somevalue
}, {
url: url, // fix the url
type: 'POST' // choose the HTTP verb
});
Fixing the url that the model uses is simple, you have also some choices:
pass the url option (like above)
override the url function of the model
Overriding the url function (source) works well for situation where every call should use a specific url, without the default id appended to it.
var MyModel = Backbone.Model.extend({
url: function() {
return _.result(this, 'urlRoot') ||
_.result(this.collection, 'url') ||
urlError();
}
});
Set the idAttribute on the model
This depends on what the id you're trying to pass means in the data.
Backbone Model uses "id" has the default id attribute name. You can specify a different name by overriding the idAttribute property of the model. Whatever the name, it is always automatically made available through the model.id property.
Now, assuming the id attribute isn't related to this model and this model's real id attribute name is something like UID, you could change the idAttribute of the model to reflect the real name of the attribute (or it could even be a string that's never going to be an attribute).
var MyModel = Backbone.Model.extend({
idAttribute: 'UID',
});
Now, the id attribute is not considered an id for the current model, and model.isNew() will return true, sending a POST request to create it on save.
Change the sync/save function behavior
If the API you're using is not RESTful, you can adjust the behaviors by overriding the sync function. This can be done on the model or collection, or on the Backbone.sync function which is used by default by the collections and models.
For example, if you wanted to make every request use POST by default for MyModel class:
var MyModel = Backbone.Model.extend({
sync: function(method, model, options) {
return Backbone.sync.call(this, method, model,
_.extend({ type: 'POST' }, options));
}
});
You could do something similar with only the save function to let the fetch do its GET request as usual.
Use the emulateHTTP setting2
If you want to work with a legacy web server that doesn't support
Backbone's default REST/HTTP approach, you may choose to turn on
Backbone.emulateHTTP. Setting this option will fake PUT, PATCH and
DELETE requests with a HTTP POST, setting the X-HTTP-Method-Override
header with the true method.
[...]
Backbone.emulateHTTP = true;
model.save(); // POST to "/collection/id", with "_method=PUT" + header.
Do not override isNew
Has this model been saved to the server yet? If the model does not yet
have an id, it is considered to be new.
Some other answers on this site suggest overriding the isNew function. Don't. The function has its purpose and overriding it to force a POST request is a poor hack, not a solution.
isNew is used internally but can also be used by your code or other libraries and Backbone plugins.
1 While I did not take this from stack overflow, it was already an answer by Andrés Torres Marroquín on a similar question.
2 Taken from Maanas Royy's answer.
I'm actually running into little problems with my current project. Following case:
I've got a model called "Posting" with relations:
public function subscribers(){
return $this->belongsToMany('User');
}
In my view-file there is a table containing all Postings and also a checkbox for subscribing/unsubscribing with the matching value to the posting-id:
<input class="click" type="checkbox" name="mobileos" value="{{{$posting->id}}}"
#if($posting->subscribers->find(Auth::User()->id))
checked="checked"
#endif
>
Now the thing I want to archive:
A JavaScript is going to watch if the checkbox is checked or not. According to that, the current user subscribes/unsubscribes to the posting. Something like:
$('.click').on('click',function() {
// $posting->find(---$(this).prop('checked')---)->subscribers()->attach(---Auth::user()->id---);
// $posting->find(---$(this).prop('checked')---)->subscribers()->detach(---Auth::user()->id---);
});
Is there any possibility to archieve that or any other ways? I couldn't get my head around this so far.
Cheers,
Chris
If you want to use Ajax to achieve this, you will need a REST endpoint in Laravel for the subscriptions, e.g.:
http://localhost/subscribe/{{userid}}
When this Endpoint is called, the database can be updated. The function could also return a JSON showing, if the saving database in the database successful.
Use this endpoint to make an Ajax Call on click:
var user = {
id: 0 // retrieve the correct ID from wherever it is stored
}
$('.click').on('click',function() {
$.GET('http://localhost/subscribe/' + user.id,
function () { // this is the success callback, that is called, if the Ajax GET did not return any errors
alert('You are subsribed')
});
});
Ideally you won't be using the GET method, but instead use POST and send the user ID as data. Also you would need to retrieve the user ID from session or wherever it is stored.
Take care that as you are using Ajax it can easily be manipulated from the client side. So on the server you should check, if the user ID that was sent is the same as in the Session. Maybe you don't need to send the user id at all, but that depends on how your backend is built.
The tutorials & guides that I've found suggest that Ember.js models are very data centric, in that you have data in the browser that is persisted to the server and/or a model is filled with data from the server.
How about something that is more verb centric? For example, my case is that, so far, I have a "Search" model, where a search has a query, a state ("beforesearch","duringsearch", etc...), and, hopefully, some results. I want for the search to then "runQuery", which fires off an ajax request to the server, which returns and fills the model with the results, and changes its state to "aftersearch".
What's the best way of handling such verbs on models? Should the "runQuery" go via ember-data, or just manually fired off using $.ajax or similar? Am I maybe thinking about models in the wrong way, and this should actually go via a controller?
Edit: After reading up a bit on REST, I think what I'm wanting is to POST to a "controller" resource. So, for example:
POST: /searches (to create a search)
POST: /searches/1/run (to execute search 1's "run" controller
Does Ember.js / ember-data have a recommended way of calling controller resources like this?
Ember-data is very oriented around using model objects that contain various information fields and relationships and are defined by a unique id. Half of my API is like what ember-data expects and half is like you described, it is more about data processing or performing a calculation than creating/retrieving/updating/deleting a data object that has an id. It doesn't make sense to treat these calculations the same and assign it an id and persist it in the database.
In my case, since I have both ember-data style data objects and calculation functionality I use a mix of ember-data and custom ajax requests. I have relational data stored that is retrieved by ember-data but I augment the models to include access to the calculation portions.
For example:
App.Event = DS.Model.extend({
name: DS.attr('string'),
items: DS.hasMany('App.Item'),
...etc...
searchData: null,
searchInEvent: function(data) {
var _this = this;
return $.ajax({
url: "/api/events/" + this.get('id') + "/search/",
dataType: 'json',
type: 'POST',
data: data
}).then(function(result){
_this.set('searchData', result);
});
}
});
App.Event is a normal ember-data model and is loaded by the router through the usual ember conventions, and as the various controllers need access to the search functionality they can access it through searchInEvent and searchData that were added to the model.
Here is a collection I define in backbone.js
var List=Backbone.Collection.extend({
model: Item,
url: "TodoApp/index.php/todo"
});
var list=new List
Then I created a Model in the collection with an ID=80
Now, when I do list.fetch();
It will make a call to
"TodoApp/index.php/todo/80"
However, at the backend, using Codeigniter, I really need to have
TodoApp/index.php/todo/get/82.........where get is a function I defined to access DB
So, should I change the Collection url to "TodoApp/index.php/todo/get"
But again, that's not really where the resource is located?
In route.php try:
$route['todo/(:num)'] = "todo/get/$1";
HERE is what I ended up doing.
I renamed the index of the controller to resource
therefore using a URL of:
TodoApp/index.php/todo/resource
When getting a GET request at
TodoApp/index.php/todo/resource/80
extract the second segment of the URI and read from DB with that.