Kayak like URL instead of query parameters - ember.js

I have a small app which reads parameters from the URL.
Example: http://localhost:4200/flights?from=FRA&to=JFK
I'd like to offer the user a Kayak like URL like:
http://localhost:4200/flights/FRA-JFK
Can this be done with Ember without doing the mapping in the webserver?
app/controllers/flights.js
import Ember from 'ember';
export default Ember.Controller.extend({
queryParams: ['from','to'],
from: null,
to: null,
filteredFromFlights: function() {
var from = this.get('from');
var flights = this.get('model');
if (from) {
return flights.filterBy('from', from);
} else {
return flights;
}
}.property('from', 'to', 'model'),
filteredFlights: function() {
var to = this.get('to');
var flights = this.get('filteredFromFlights');
if (to) {
return flights.filterBy('to', to);
} else {
return flights;
}
}.property('from', 'to', 'model')
});

You could add nested route (say from-to), so flights route is responsible for finding flights, from-to route is responsible for local filtering flights by param.
//router
this.route('flights', function() {
this.route('from-to', {path: '/:from_to'});
});
//flights route
model: function() {
return this.store.find('flight');
}
//from-to route
model: function(params) {
var splited = params.from_to.split('-');
return {
from: splited[0],
to: splited[1],
model: this.modelFor('flights');
};
},
setupController: function(controller, models) {
controller.setProperties(models);
}
//from-to controller
filteredFlights: function() {
//...
}.property('from', 'to', 'model.[]'),
filteredFromFlights: function() {
//...
}.property('from', 'to', 'model.[]'),

Related

Set multiple data with Ember and make it persist on Firebase

I am trying to set data from two models (that has hasMany & belongsTo relationship) and save them to firebase.
'list' data ends up being saved to firebase but not user data.
I think I'm doing something wrong at step 3. I'd appreciate your help!
import Ember from 'ember';
export default Ember.Route.extend({
model: function() {
return this.store.find('list');
},
actions: {
createList: function() {
var newListTitle = this.controllerFor('lists').get('newListTitle');
var username = this.get('session.user.displayName');
alert(this.get('session.user.displayName'));
if (Ember.isBlank(newListTitle)) { return false; }
//1
var list = this.store.createRecord('list', {
title: newListTitle,
user: username,
});
//2
this.controllerFor('lists').set('newListTitle', '');
var _this = this;
//3
list.save().then(function(list) {
user.get('lists').addObject(list);
user.save();
_this.transitionTo('lists.show', list); //4
});
}
}
});
Restructured your adding logic as well as user defined models, also modified your route, which could look like this in Edit and View mode. Meaning you can have more than one item returned from "model".
// Update models
App.List = DS.Model.extend({
value: DS.attr('string')
});
App.User = DS.Model.extend({
name: DS.attr('string')
});
App.UserLists = DS.Model.extend({
user: DS.belongsTo('user'),
list: DS.belongsTo('list')
});
export default Ember.Route.extend({
LIST:SHOW ROUTE
model: function(params) {
var store = this.get('store');
var userPromise = store.find('user', params.id);
return Ember.RSVP.hash({
user: userPromise,
userList : userPromise.then(function(user) {
return store.find(userList, { WhereUserIdIs : user.get('id') })
});
});
},
actions: {
createList: function() {
var self = this;
var failure = function(reason) {
// handle stuff
};
var list = this.store.createRecord('list', {
title: this.get('title'),
});
var user = this.get('user');
var usersList = store.createRecord('userList', {
'user': user,
'list': list
});
list.save().then(function(list) {
user.save().then(function() {
userList.save().then(function() {
self.transitionTo('lists.show', list.get('id'));
}, failure);
}, failure);
}, failure);
}
});

Ember.js Fixture findQuery

I'm trying to change my URLs in Ember to use a property on a model (title), instead of the ID. I can get everything to work if I click on a link-to, but when I do a fresh reload of the models route, everything seems to fall apart. Within queryFixtures I can get return the desired item, and logs to the console by logging 'experiment' to the console in the model hook.
App.ExperimentRoute = Ember.Route.extend({
serialize: function(experiment, params) {
return {
experiment_title: experiment.get('urlFriendlyName')
}
},
model : function(params) {
experiment = this.get('store').find('experiment', { title: params.experiment_title });
return experiment;
}
});
My store:
App.Store = DS.Store.extend({
adapter: DS.FixtureAdapter.extend({
queryFixtures: function(fixtures, query, type) {
function urlFriendlyTitle(title) {
var ret = title.replace(/ /g,"-"); // replace spaces
// do other replacements that make sense in your case, e.g.:
ret = ret.replace(/&/g,"and");
//... and so on and so forth
// encode the remaining characters
ret = ret.toLowerCase();
ret = encodeURIComponent(ret);
return ret;
}
return fixtures.filter(function(item) {
if(urlFriendlyTitle(item.title) == query.title) {
// console.log(item);
return item;
}
});
}
})
});
UPDATE:
App.ExperimentRoute = Ember.Route.extend({
model : function(params) {
experiment = this.get('store').find('experiment', { });
console.log(Ember.inspect(experiment))
return experiment;
}
});
Running the above outputs '<DS.PromiseArray:ember325>' in the console
App.Router.map(function () {
// Add your routes here
this.resource('category', { path: '/:category_id'}, function() {
this.resource('experiment', { path: '/:experiment_title' }, function() {
this.resource('device', { path: '/:device' });
});
});
});
App.ExperimentRoute = Ember.Route.extend({
setupController: function(controller, model) {
console.log(Ember.inspect(model))
console.log(Ember.inspect(controller))
}
})
This route outputs <App.ExperimentController:ember388> <DS.AdapterPopulatedRecordArray:ember326>

ArrayController Not Updating When Deleting Records

using ember-data 1.0.0-beta.5 and have the following routes and router
App.Router.map(function () {
this.resource('users', function () {
this.route('new');
});
this.resource('user', { path: '/user/:id' }, function () {
this.route('edit');
});
});
App.UsersIndexRoute = Ember.Route.extend({
model: function(){
return this.store.findAll('user');
},
setupController: function (controller, data) {
this._super(controller, data);
}
});
App.UserEditRoute = Ember.Route.extend({
model: function() {
return this.store.find('user', this.modelFor("user").id);
},
setupController: function (controller, data) {
this._super(controller, data);
},
actions: {
delete: function(){
var router = this;
var model = this.currentModel;
model.destroyRecord().then(function(){
router.transitionTo('users');
});
}
}
});
However when i transition back to the users route the ArrayController still has the deleted object in it. Any ideas as to why this is or how to wait until it is removed before transitioning?
kind of a work around but solves the problem.
in the UsersIndexContoller add a array to store the deleted ids
App.UsersIndexController = Ember.ArrayController.extend({
deleted: []
});
Then just append the id of the deleted model to this array and filter in the setupController method.
App.UsersEditRoute = Ember.Route.extend({
delete: function(){
var router = this;
var model = this.currentModel;
var usersController = this.controllerFor('users.index');
model.destroyRecord().then(function(){
usersController.get('deleted').push(model.id);
router.transitionTo('users');
});
}
}
});
App.UsersIndexRoute = Ember.Route.extend({
setupController: function (controller, data) {
var deleted = this.controller.get('deleted');
var filtered = data.filter(function(user){
return !deleted.contains(user.id);
});
data.set('content', filtered);
this._super(controller, data);
}
});
In your case since you want to refetch all of the users and your server lies to you about deleting the record (or it happens later), you might contemplate transitioning then deleting.
delete: function(){
var model = this.currentModel;
this.transitionTo('users').then(function(){
model.destroyRecord();
});
}

Why don't nested resources in Ember.js preserve the params hash?

Given the following Ember.js application (using Ember 1.0.0.rc.6.1 and Ember Data 0.13):
App = Ember.Application.create({ LOG_TRANSITIONS: true });
App.Store = DS.Store.extend();
App.Router.map(function() {
this.resource('promotions', function() {
this.resource('promotion', { path: '/:promotion_id' }, function() {
this.resource('entrants', function() {
this.resource('entrant', { path: '/:entrant_id' });
});
});
});
});
App.PromotionRoute = Ember.Route.extend({
model: function() {
return { id: 1, name: 'My Promotion' };
}
});
App.EntrantsIndexRoute = Ember.Route.extend({
model: function(params) {
console.warn('EntrantsIndexRoute', '\nparams:', params, '\nparams.promotion_id:', params.promotion_id, '\narguments:', arguments);
console.log('params should be:', { promotion_id: 1 });
console.log('The queried URL should be:', '/entrants?promotion_id=1');
return App.Entrant.find({promotion_id: params.promotion_id});
}
});
App.Entrant = DS.Model.extend({
name: DS.attr('string')
});
If you enter the url #/promotions/1/entrants, which should be a nested resource, the params is an empty object. How can I access promotion_id there? JSFiddle here, take a look at the console after clicking on "Click me": http://jsfiddle.net/Kerrick/4GufZ/
While you can't access the dynamic segments of the parent route, you still can retrieve the model for the parent route and get its ID, like this:
App.EntrantsIndexRoute = Ember.Route.extend({
model: function() {
var promotion_id = this.modelFor('promotion').id;
return App.Entrant.find({ promotion_id: promotion_id });
}
});
Or, if there is a has-many relation between promotion and entrants, you even might do:
App.EntrantsIndexRoute = Ember.Route.extend({
model: function() {
return this.modelFor('promotion').get('entrants');
}
});
Try this code:
App.EntrantsIndexRoute = Ember.Route.extend({
model: function() {
var promotion_id = this.modelFor('promotion').query.promotion_id;
return App.Entrant.find({ promotion_id: promotion_id });
}
});

Trigger a model.get('transaction').rollback() from the deactivate hook in a route

How can I do a get('transaction').rollback() or deleteRecord() of the model in the deactivate route hook when the model is isNew? I can't figure out how to access the model from within the hook.
app.js
App.Router.map(function() {
this.resource('users', function() {
this.route('new');
})
});
App.UsersNewRoute = Ember.Route.extend({
model: function() {
return App.User.createRecord();
},
activate: function() {
this.controllerFor('users').set('newUserCreate', true);
},
deactivate: function() {
this.controllerFor('users').set('newUserCreate', false);
}
});
This is the code that does a rollback() on the model:
deactivate: function() {
this.controllerFor('users').set('newUserCreate', false);
if (this.currentModel.get('isNew')) {
this.currentModel.get('transaction').rollback();
}
Special thanks to #sly7_7 for solving this.
Route objects know about their controllers. You should also be able to do this:
deactivate: function() {
var model = this.get('controller.content');
if (model.get('isNew')) {
model.deleteRecord();
};
};