URL : http://localhost:3000/dashboard?ID=10400&Name=10400
I'm trying to get the query params ID and Name from the URL but I get undefined. I have also tried backbone-queryparams but still it does not work. Any idea how to get the current URL with params in Backbone Marionette
define([
'jquery',
'backbone',
'marionette',
'modules/dashboard/controllers/dashboardController',
'backbone.queryparmas'
], function ($, Backbone, Marionette, Controller) {
'use strict';
return Marionette.AppRouter.extend({
appRoutes: {
'': 'dashboard'
},
initialize: function(){
console.log( Backbone.history.fragment ); // getting undefined
},
controller: new Controller()
});
});
I had to do this to get the query params. Not sure if there is any better way.
messagedashboard: function () {
var searchParams = window.location.search.slice(1); // returns 'ID=10400&Name=10400'
var getParamsFromSearchParams = $.deparam(searchParams); //changes into object
}
For using $.deparam check jquery.bbq library.
From the example here (https://stackoverflow.com/a/11671457/3780922), it looks like the best option is to set a route with a catchall parameter, which will give you the entire query string.
appRoutes: {
'': 'showDash', //default for blank/empty route
'dashboard': 'showDash',
'dashboard?*queryString' : 'showDash'
},
showDash: function (queryString) {
var params = parseQueryString(queryString);
if(params.foo){
// foo parameters was passed
}
}
You'll have to write your own query string parser, however, but if it is not null, then you have your query parameter passed in the queryString object, which in your example would be "ID=10400&Name=10400"
Related
I have a backboneJS app that has a router that looks
var StoreRouter = Backbone.Router.extend({
routes: {
'stores/add/' : 'add',
'stores/edit/:id': 'edit'
},
add: function(){
var addStoresView = new AddStoresView({
el: ".wrapper"
});
},
edit: function(id){
var editStoresView = new EditStoresView({
el: ".wrapper",
model: new Store({ id: id })
});
}
});
var storeRouter = new StoreRouter();
Backbone.history.start({ pushState: true, hashChange: false });
and a model that looks like:
var Store = Backbone.Model.extend({
urlRoot: "/stores/"
});
and then my view looks like:
var EditStoresView = Backbone.View.extend({
...
render: function() {
this.model.fetch({
success : function(model, response, options) {
this.$el.append ( JST['tmpl/' + "edit"] (model.toJSON()) );
}
});
}
I thought that urlRoot when fetched would call /stores/ID_HERE, but right now it doesn't call that, it just calls /stores/, but I'm not sure why and how to fix this?
In devTools, here is the url it's going for:
GET http://localhost/stores/
This might not be the answer since it depends on your real production code.
Normally the code you entered is supposed to work, and I even saw a comment saying that it works in a jsfiddle. A couple of reasons might affect the outcome:
In your code you changed the Backbone.Model.url() function. By default the url function is
url: function() {
var base =
_.result(this, 'urlRoot') ||
_.result(this.collection, 'url') ||
urlError();
if (this.isNew()) return base;
return base.replace(/([^\/])$/, '$1/') + encodeURIComponent(this.id);
},
This is the function to be used by Backbone to generate the URL for model.fetch();.
You added a custom idAttribute when you declared your Store Model to be like the one in your DB. For example your database has a different id than id itself, but in your code you still use new Model({ id: id }); when you really should use new Model({ customId: id });. What happens behind the scenes is that you see in the url() function it checks if the model isNew(). This function actually checks if the id is set, but if it is custom it checks for that:
isNew: function() {
return !this.has(this.idAttribute);
},
You messed up with Backbone.sync ... lots of things can be done with this I will not even start unless I want to make a paper on it. Maybe you followed a tutorial without knowing that it might affect some other code.
You called model.fetch() "a la" $.ajax style:
model.fetch({
data: objectHere,
url: yourUrlHere,
success: function () {},
error: function () {}
});
This overrides the awesomeness of the Backbone automation. (I think sync takes over from here, don't quote me on that).
Reference: Backbone annotated sourcecode
I'm using Controller to Fetch URL. I need a way to put Parameter in this POST. These Parameters are selected by users on View & Not Stored yet(I do not know how to store)
Currently I managed to
Display & Route The View with search result coming from API
Display and refresh the page when someone selects a Filter Option
Problem
I got no idea how to record what the users clicked
How do i "re-post" so i can get the new set of results
I read and say people saying POST Fetch should be done in Model ,
Collection is for Store Multiple Models which i don't know in this
scenario?
Collections
Jobs.js
define([
'jquery',
'underscore',
'backbone',
'models/filter'
], function($, _, Backbone,JobListFilterModel){
var Jobs = Backbone.Collection.extend({
url: function () {
return 'http://punchgag.com/api/jobs?page='+this.page+''
},
page: 1,
model: JobListFilterModel
});
return Jobs;
});
Collections Filter.JS
define([
'jquery',
'underscore',
'backbone',
'models/filter'
], function($, _, Backbone,JobListFilterModel){
console.log("Loaded");
var Jobs = Backbone.Collection.extend({
url: function () {
return 'http://punchgag.com/api/jobs?page='+this.page+''
},
page: 1,
model: JobListFilterModel
});
// var donuts = new JobListFilterModel;
// console.log(donuts.get("E"));
return Jobs;
});
Models
Filter.js
define([
'underscore',
'backbone'
], function(_, Backbone){
var JobFilterModel = Backbone.Model.extend({
defaults: {
T: '1', //Task / Event-based
PT: '1', //Part-time
C: '1', //Contract
I: '1' //Internship
}
});
// Return the model for the module
return JobFilterModel;
});
Models
Job.js
define([
'underscore',
'backbone'
], function(_, Backbone){
var JobModel = Backbone.Model.extend({
defaults: {
name: "Harry Potter"
}
});
// Return the model for the module
return JobModel;
});
Router.js
define([
'jquery',
'underscore',
'backbone',
'views/jobs/list',
'views/jobs/filter'
], function($, _, Backbone, JobListView, JobListFilterView){
var AppRouter = Backbone.Router.extend({
routes: {
// Define some URL routes
'seeker/jobs': 'showJobs',
'*actions': 'defaultAction'
},
initialize: function(attr)
{
Backbone.history.start({pushState: true, root: "/"})
},
showJobs: function()
{
var view = new JobListView();
view.$el.appendTo('#bbJobList');
view.render();
console.log(view);
var jobListFilterView = new JobListFilterView();
jobListFilterView.render()
},
defaultAction: function(actions)
{
console.info('defaultAction Route');
console.log('No route:', actions);
}
});
var initialize = function(){
console.log('Router Initialized');// <- To e sure yout initialize method is called
var app_router = new AppRouter();
};
return {
initialize: initialize
};
});
Some Examples would be awesome. Thank you
Fetching means to retrieve (as you probably know), to GET from the server some information.
POST is usually for creating new resources. For instance, saving a new Job would be a POST on the /jobs URL in a REST like API.
In your case, what you probably want is a:
JobCollection which would extend from Backbone Collection and use a JobModel as the model
JobModel which would represents a Job.
You currently already have the JobModel but it has no Collection... And instead you have a Collection of JobFilters, which means that you are handling multiple set of filters. That's probably not what you had in mind?
Assuming you now have a JobCollection that represents the list of all the jobs your views will display, when you do a collection.fetch() on it, it'll GET all the jobs, without any filters.
The question now becomes: how do I pass extra parameters to fetch() in a collection?
There are many ways to do that. As you already have a JobFilterModel, what you can do in your JobFilterModel is implement a method such as:
//jobCollection being the instance of Job collection you want to refresh
refreshJobs: function(jobCollection) {
jobCollection.fetch({reset: true, data: this.toJSON()});
}
A model's toJSON will transform the Model into a nice Javascript object. So for your JobFilterModel, toJSON() will give back something like:
{
T: '1', //Task / Event-based
PT: '1', //Part-time
C: '1', //Contract
I: '1' //Internship
}
Putting it in the data property of the Collection's fetch() option hash will add those to the query to the server. Then, whatever jobs your server answer with, they will be used to reset (that's why reset: true in the options, otherwise it just updates) the collection of jobs. You can then bind in your views on jobCollection "reset" event to know when to re-render.
So, now, your JobFilterModel only 'job' is to store (in memory) the filters the user has chosen, and the JobCollection and JobModel don't know anything about the filters (and they shouldn't). As for storing the JobFilterModel's current status, you can look at Backbone localstorage plugin or save it on your server / get it from your server (using the model's fetch() and save() method).
I hope this helps!
I want to pass an argument when routing in a Backbone.js application
Here is the transcript
var AppRouter = Backbone.Router.extend({
routes: {
'toolSettings/(:action)' : 'toolSettings'
}
});
var initialize = function() {
var app_router = new AppRouter;
app_router.on('route:toolSettings', function(actions) {
toolSettingsRoute.route();
});
Backbone.history.start();
};
On the UI I've a <a href="toolSettings/target" /> link which would invoke the toolSettingsRoute.route().
I want pass this action argument in the route method and i've to pass it to further proceedings.
I tried toolSettingsRoute.route(action) and it's not giving any error, though how do i use this argument in the toolSettingsRoute.js file
I'd like to know how we can pass arguments correctly and utilize them in the subsequent js
One options is to define your route functions in your router and you can just pass the parameter in to that function:
var AppRouter = Backbone.Router.extend({
routes: {
'toolSettings/(:action)': 'toolSettings'
},
toolSettings: function (action) {
// whatever
}
});
E X A M P L E
http://jsfiddle.net/mreis1/Nt9tm/1/
var AppRouter = Backbone.Router.extend({
routes: {
'toolSettings/:action' : 'toolSettings'
},
toolSettings:function (action){
//do whatever you want to do with the action parameter
}
});
So, I'm trying to build routes in my Ember application dynamically with data from an API endpoint, /categories, with Ember Data. In order to do this, I'm adding a didLoad method to my model, which is called by the controller and set to a property of that controller. I map the route to my router, and all that works fine. The real trouble starts when I try to set up a controller with a content property set by data from the server retrieved by findQuery.
This is the error:
TypeError {} "Object /categories/548/feeds has no method 'eachRelationship'"
This is the code:
window.categoryRoutes = [];
App.Categories = DS.Model.extend({
CATEGORYAFFINITY: DS.attr('boolean'),
CATEGORYID: DS.attr('number'),
CATEGORYNAME: DS.attr('string'),
CATEGORYLINK: function () {
var safeUrl = urlsafe(this.get('CATEGORYNAME'));
categoryRoutes.push(safeUrl);
return safeUrl;
}.property('CATEGORYNAME'),
didLoad: function () {
var categoryLink = this.get('CATEGORYLINK');
var categoryId = this.get('CATEGORYID');
App.Router.map(function () {
this.resource(categoryLink, function () {
// some routes
});
});
App[Ember.String.classify(categoryLink) + 'Route'] = Ember.Route.extend({
setupController: function(controller, model) {
// source of error
this.controllerFor(categoryLink).set(
'content',
this.store.findQuery('/categories/' + categoryId + '/feeds', {
appid: 'abc123def456',
lat: 39.75,
long: -105
})
);
}
});
}
});
Any 'halp' is appreciated!
Also, if I'm doing this completely wrong, and there's a more Ember-like way to do this, I'd like to know.
I figured this out. I got this error because I was passing in a string instead of a real 'type' from the App.Helpers object to an extract method in some custom RESTAdapter code I had overridden.
The solution is to pass in the corresponding model helper in App.Helpers using my custom type name.
Something like this in the overridden RESTAdapter.serializer.extractMany method:
var reference = this.extractRecordRepresentation(loader, App.Helpers[root], objects[i]);
I am new in SPA's with backbone and I am trying to develop a small app by using backbone and requireJs.
The problem I faced is that I can't extend a view by passing a collection.
Well, this is the view with name MenuView.js
define([
'Backbone'
], function (Backbone) {
var MenuView = Backbone.View.extend({
tagName: 'ul',
render: function () {
_(this.collection).each(function (item) {
this.$el.append(new MenuListView({ model: item }).render().el);
}, this);
return this;
}
});
return new MenuView;
});
and this is the router.js in which the error is appeared
define([
'Underscore',
'Backbone',
'views/menu/menuView',
'views/createNew/createNew',
'collections/menu/menuCollection',
], function (_, Backbone, MenuView, CreateNewView,Menucollection) {
var AppRouter = Backbone.Router.extend({
routes: {
'index': 'index',
'action/:Create': 'Create'
},
index: function () {
CreateNewView.clear();
//----------- HERE IS THE PROBLEM ------------
$('#menu').html(MenuView({ collection: Menucollection.models }).render().el);
},
Create: function () {
CreateNewView.render();
}
});
var initialize = function () {
var appRouter = new AppRouter();
Backbone.history.start();
appRouter.navigate('index', { trigger: true });
};
return {
initialize: initialize
};
});
The error message is "object is not a function". I agreed with this since the MenuView is not a function. I tried to extend the MenuView (MenuView.extend({collection:Menucollection.models})) and the error message was "objet[object,object] has no method extend".
I suppose that the way I am trying to do this, is far away from the correct one.
Could anyone suggest how to do this?
Thanks
#Matti John's solution will work, but it's more of a workaround than a best practice IMHO.
As it is, you initializing your view just by requiring it, which:
Limits you to never accept arguments
Hits performance
Makes it really hard to unit-test if you relay on assigning properties ater constructing an instance.
A module should be returning a 'class' view and not an instance on that view.
In MenuView.js I would replace return new MenuView with return MenuView; and intitalzie it when required in router.js.
Your MenuView.js returns an initialized MenuView, so you could just do:
MenuView.collection = Menucollection
Note I haven't selected the models - I think it's better if you don't use the models as a replacement for your view's collection, since it would be confusing to read the code and not have a Backbone collection as the view's collection. You would also lose the method's contained within the collection (e.g. fetch/update).
If you do this, then you would need to update your loop (each is available as a method for the collection):
this.collection.each(function (item) {
this.$el.append(new MenuListView({ model: item }).render().el);
}, this);