Use dynamic url for Backbone Collection - url

Backbone configure url once for all when a Collection is created. Is there a way to change this url later?
The following sample shows 2 POST at /product and 2 POST at /product/id/stock. The last POST won't work, Backbone concatenate the id and try to PUT it, but I don't know why.
products.create({ name: 'American Pastoral', price: 8 });
products.create({ name: 'The Grapes of Wrath', price: 10 });
products.each(function(product) {
var id = parseInt(product.get('id'));
stocks.setId(id);
stocks.create({ id: id, quantity: 12 });
}
The stock collection:
Backbone.Collection.extend({
url: function() {
return this.url;
},
parse : function(resp) {
return resp.stock;
},
setProduct: function(id) {
this.url = '/product/'+id+'/stock';
}
});
This won't work.

Backbone.js will use the url of the model when saving existing models. Its not quite clear what you are trying to do -- I don't know what stocks is, for instance. Anyway, your code probably needs to look similar to the below and you should not be dynamically changing the url:
Product = Backbone.Model.extend({
url: function() {
return '/product/' + id + '/stock';
}
});
ProductList = Backbone.Collection.extend({
model: Product,
url: '/product'
}):
Backbone.js will then use collection url for creates and the model url for saves. I think you need to leave the url alone and let backbone's default functionality handle it.

I have run into what is essentially the same problem. It seems that Backbone's pattern is to lock down relative URI's in models and collections and allow the framework to use these to build final the final URI for a given resource. This is great for Restful URI's templates that don't change. But in a pure RESTful service you would expect lists of relative URI's to come down as part of a given resource. There are many reasons why you might need to do this, obvious one is if the URI for a resource moves.
As far as I can tell Backbone has no way of easily cleanly handling this. In the question above my workaround is to essentially redefine the models url method using OLN. You would do this while fetching a collection or initializing it for the first time. Basically build the logic to handle URI lists yourself.

I know this is an old question, but it took me a bit to determine how to solve it for my problem. In the manual under the fetch operation there is this tidbit:
jQuery.ajax options can also be passed directly as fetch options, so to fetch a specific page of a paginated collection: Documents.fetch({data: {page: 3}})
The object being passed to the data parameter is added as a URL GET variable. So URL would turn into URL?page=3 or URL?x=1&page=3 if there were existing variables already.

Related

Grails dynamic url mapping

I have a product list I'm trying to create SEO-friendly URLs for.
Example
domain.com/product/cell-phone-razor
"cell-phone-razor" is dynamic from the db
I have successfully achieved this behavior with the following code
"/product/$url"(controller: "product", action:"show")
However there becomes an issue when trying to map other actions non related to the page URL. Example I have an Ajax URL domain.com/product/setPrice which is being mapped to the show action.
I was able to work around this by adding the following to my urlmapping in addition to the previous mapping.
"/product/setPrice" {
controller = "product"
action = "setPrice"
}
Is there a better way to config my url mapping so that I don't need to add rules for every action mapping?
In our application we use the following approach - not saying the perfect one. Basically we're appending URL fragments (that are happily ignored by search engines) to the SEO parts of the URL.
name product: "/$productName-p$productId" {
controller = 'product'
action = 'show'
constraints {
productName matches: '.+'
productId matches: '^[0-9]+$'
}
}
In your case the url should look like domain.com/product/cell-phone-razor-p123455 where 123456 is the product id.
Although not as dynamic as I'd like, but this seems to be the best solution.
"/product/$url"(controller: "product", action:"show") {
constraints {
url(validator: {
return !(it in
['setPriceAction', 'setAnotherAction']
)
})
}
}

How to stop Backbone sending calculated values back to the server when doing model.save?

Say I have a person model, with a name attribute.
Server-side, when I create a JSON representation of the model, I include a calculated value:
name: 'Jack'
name_backwards: 'kcaJ' # example
Client-side, when I do backbone_model.save(attributes), it includes name_backwards in the object it sends to the server. This isn't ideal, because it doesn't correspond to an actual attribute on the server.
PATCH is not an option because I'm using Rails 3.2. Is there any way around this issue?
Seems a bit odd to me that your server is sending something out that it won't accept back. I see two options:
Filtering out an incoming name_backwards in your controller.
Stop sending name_backwards and let the client deal with it.
1 is easy, just delete :name_backwards from the appropriate part of params.
2 is a little more involved. First you'd stop adding name_backwards to the JSON that goes out. Then you could add name_backwards in your model's parse:
parse: function(response) {
response.name_backwards = reverse(response.name);
return response;
}
See this answer for a reliable way to reverse a string in JavaScript.
Then you'll want to ignore name_backwards in your model's toJSON:
toJSON: function() {
var o = _(this.attributes).clone(); // This is what the standard toJSON does.
delete o.name_backwards;
return o;
}
Then add a serialize method to use instead of toJSON when you're feeding your models to your templates:
serialize: function() {
return _(this.attributes).clone();
}
You can easily patch serialize into Backbone.Model.prototype if you want an easy way to have a consistent interface between your models and templates.
Override the toJSON method in your Backbone.Model subclass and select only the canonical fields from this.attributes.

Routing in the DNN 6.2 Services Framework

So I have the basic Hello World service running in DNN 6.2 Services Framework, which is based on MVC. The route, taken from example, is:
routeManager.MapRoute("MyServices", "{controller}/{action}", new[] { "HelloWorldServices" });
When my action go to ~/DesktopModules/MyServices/API/Welcome/HelloWorld, it calls the HelloWorld function and works. So far, I've managed to figure out that I can do this:
routeManager.MapRoute("MyServices", "{controller}/{action}/{userID}", new[] { "HelloWorldServices" });
When I go to ~/DesktopModules/MyServices/API/Welcome/users, it calls the users function, which has an optional parameter for the ID, and that is working. But now I want to make an endpoint ~/DesktopModules/MyServices/API/Welcome/locations, which could take a location ID. I can't just write this:
routeManager.MapRoute("MyServices", "{controller}/{action}/{locationID}", new[] { "HelloWorldServices" });
or even
routeManager.MapRoute("MyServices", "{controller}/locations/{locationID}", new[] { "HelloWorldServices" });
It doesn't work that way. Whichever is first (users or locations) recognizes the ID and whichever is second does not. While I can figure out what does not work, I have no idea what will work, and have not been able to find out despite a lot of searching. I also found some examples that look like this:
routeManager.MapRoute("Html", "default", "", new { controller = "Service", action = "GetTabs" }, new[] { "DotNetNuke.Modules.Html" });
But I can't figure out how that works, either. Eventually I'll want to do "~/DesktopModules/MyServices/API/Welcome/users/userid/locations/" as well. If anyone could give me some examples, that would be much appreciated!
UPDATE: Based on the answer I looked up MVC routing. I realized I had to write it generically, and now have these working:
{controller}/{action}
{controller}/{action}/{id}
{controller}/{action}/{id}/{secondaction}
{controller}/{action}/{id}/{secondaction}/{secondid}
"id", "secondaction", and "secondid" are all optional string parameters. So I can have "users/userid/locations/locationid"... the "locations/locationid" part is handled in the "users" function.
My general recommendation here would be to use a route map that is something like
{controller}/{action}/{id}
This is a typical default ASP.NET MVC route style. Then you could have a Users Method that as an optional id parameter, and a locations method with an optional id parameter, etc.
This will give you a truly dynamic route, and is a LOT easier to manage

What is the best way to handle multiple aiax requests and responses?

I have a web application that uses VB.NET MVC for the server side code. I set up the client side JavaScript to easily send and receive data to the server Controller functions. Basically what I did was create a JavaScript "request" object that uses Ajax to call a controller function and pass in parameters. I let MVC do all of the serialization for me. Then the controller function returns a JSON, usually with a block of HTML as a string. Since I am handling all of the ajax calls in one place, I can't figure out a good way to handle the responses. When the ajax response comes back, I have no way of knowing which request it came from. The website has a lot going on so the responses all need to be handled differently and all return different data.
Right now what I do is in the controller function I send back some key along with the block of HTML, then in the ajax complete function I check for all of these specific keys. Doing it this way makes the javascript code difficult to manage.
var postData = { id=0 };
$.ajax({
type: "POST",
url: "/Controller/Action/"
data: postData
}).done(function (data) {
if (data.Foo) {
Foo(data);
} else if(data.Bar) }
Bar(data);
}
});
I am having trouble researching this because I don't know which keywords to look up. I think I'm going to try and do something where I call the function names dynamically in the ajax done function, but I was wondering if there are any existing libraries or code examples that do larger scale ajax request functions like this.
Maybe the problem comes from the idea of "doing all the stuff in one place". I can imagine that it will be very difficult to maintain your code once you have 40 chained if...else if... in one method. Maybe splitting things up a bit wont hurt after all.
Anyway, one way of doing it the way you want it would be instead of passing a key, passing the name of the javascript function as a delegate. Then call window[data.funcName](data); in done().
Say your json is
{
foo: "bar",
funcName: "DoMyFoo"
}
This is how your call would look like :
var postData = { id=0 };
$.ajax({
type: "POST",
url: "/Controller/Action/"
data: postData
}).done(function (data) {
window[data.funcName](data);
});
function DoMyFoo(d){
//Do your specific stuff here
alert(d.foo);
}
See this question How to execute a JavaScript function when I have its name as a string for info and examples.
Edit: If your functions lies within an object instance instead of the global namespace, say obj, you can call it the same way with obj['myFunction'](args)

In MVC3 how do I have a dropdown that shows/hides fields based on the selected value?

I have a dropdown of countries, and an address form. Depending on the country selected, I want to hide/show certain fields. I'm quite new to MVC and MVC3, what is the best way to do this?
I have on the page a 'DropDownListFor' that populates correctly. When this changes, I imagine I need to ask the server which fields to show/hide. I could perhaps put some JQuery into a change event that calls a method, and it returns some json saying visible:true for each field, but I don't know if that's ideal or even how to implement it (possibly $.ajax or something).
Any ideas?
Edit: I should add the hard part of this is asking the server what fields to show for each country as there are many countries and the possibilities are all stored in the database. I am accustomed to webforms not MVC so I would ordinarily postback and have serverside logic, but this isn't an option with MVC afaik...
I have deleted my first answer as it was irrelevant.
With MVC3 you can send an AJAX request to any method.
In HomeController.cs:
public List<string> GetFieldsToShow(string id)
{
// if you routing is left to default, the parameter passed in will be called 'id'
// Do what you gotta do...
List<string> listOfFieldsToShowBasedOnCountry = GetList(id);
return listOfFieldsToShowBasedOnCountry;
}
And in the AJAX call, something like...
$.ajax({
type: 'POST',
url: '/Home/GetFieldsToShow/' + valueOfSelectedDropDownItem,
/*etc...*/
success: function(data){
$(data).each(function(){
$('#' + this).show();
}
}
});

Resources