How to pass Error Message to Route from a different Controller in Ember js - ember.js

Let, I have two routes and two controllers namely login and signup
If I signup successfully then I want to perform transition to the route login with a success message as parameter,
/app/signup/controller.js
import Controller from '#ember/controller';
export default Controller.extend({
actions: {
signup: function(){
let _this = this;
let successMessage = 'successfully registered';
var credentials = this.getProperties('name','identification','password');
let list = this.store.createRecord('user', {
name: credentials.name,
email: credentials.identification,
password: credentials.password
});
list.save().then(function(){
_this.transitionToRoute('login','successMessage');
});
}
}
});
app/login/template.hbs
<body>
{{successMessage}}
</body>
/app/router.js
import EmberRouter from '#ember/routing/router';
import config from './config/environment';
const Router = EmberRouter.extend({
location: config.locationType,
rootURL: config.rootURL
});
Router.map(function() {
this.route('login');
this.route('signup');
});
export default Router;

I think you sort of have 3 options:
Use a route param (query param or positional)
Use a service to manage login stuff, and read some computed property from the service representing your state / message from your login controller
Use a flash/toast style UI where the message lives outside of the app view/component hierarchy
Personally, for where you want to display your message, I'd go for #2, which would look like this:
// app/services/user-session.js
import Service from '#ember/service';
export default class extends Service {
successMessage = null;
signup(name, id, password) {
// logic
this.set('successMessage', 'yay');
}
}
// app/controllers/signup.js
import Controller from '#ember/controller';
import { service } from '#ember-decorators/service';
import { action } from '#ember-decorators/object';
export default class extends Controller {
#service userSession;
#action
signup() {
this.userSession.signup(...);
this.transition...
}
}
// app/controllers/login.js
import Controller from '#ember/controller';
import { service } from '#ember-decorators/service';
import { readOnly } from '#ember-decorators/object/computed';
export default class extends Controller {
#service userSession;
#readOnly('userSession.successMessage') successMessage;
}
Or, in the old syntax:
// app/services/user-session.js
import Service from '#ember/service';
export default Service.extend({
successMessage: null,
signup(name, id, password) {
// logic
this.set('successMessage', 'yay');
}
});
// app/controllers/signup.js
import Controller from '#ember/controller';
import { inject as service } from '#ember/service';
export default Controller.extend({
userSession: service(),
actions: {
signup() {
this.userSession.signup(...);
this.transition...
}
}
});
// app/controllers/login.js
import Controller from '#ember/controller';
import { inject as service } from '#ember/service';
import { readOnly } from '#ember/object/computed';
export default Controller.extend({
userSession: service(),
successMessage: readOnly('userSession.successMessage')
});
hope this helps

Related

Using and binding JSONAPI attributes data in ember js

I have an ember.js toy application that I want to hook into a JSONAPI REST service for obtaining and displaying data. I can trace in my browser's developer console, that indeed, ember-data initiates the appropriate GET requests and receives proper, valid JSONAPI response bodies.
// ./app/models/person.js
import DS from 'ember-data';
export default DS.Model.extend({
name: DS.attr('string'),
email: DS.attr('string'),
birthdate: DS.attr('string')
});
// ./app/adapters/person.js
import ApplicationAdapter from './application';
export default ApplicationAdapter.extend({
pathForType() {
return "persons";
}
});
// ./app/adapters/application.js
import DS from 'ember-data';
export default DS.JSONAPIAdapter.extend({
host: 'http://localhost:5000'
});
// ./app/router.js
import EmberRouter from '#ember/routing/router';
import config from './config/environment';
const Router = EmberRouter.extend({
location: config.locationType,
rootURL: config.rootURL
});
Router.map(function () {
this.route('persons', function() {
this.route('show', { path: '/:person_id' });
});
});
export default Router;
// ./app/routes/persons/show.js
import Route from '#ember/routing/route';
export default Route.extend({
model(params) {
return this.get('store').findRecord('person', params.person_id);
}
});
// ./app/routes/persons/index.js
import Route from '#ember/routing/route';
export default Route.extend({
model() {
return this.get('store').findAll("person");
}
});
// ./app/routes/application.js
import Route from '#ember/routing/route';
export default Route.extend({
});
// ./app/app.js
import Application from '#ember/application';
import Resolver from './resolver';
import loadInitializers from 'ember-load-initializers';
import config from './config/environment';
const App = Application.extend({
modulePrefix: config.modulePrefix,
podModulePrefix: config.podModulePrefix,
Resolver
});
loadInitializers(App, config.modulePrefix);
export default App;
// ./app/resolver.js
import Resolver from 'ember-resolver';
export default Resolver;
Unfortunately, when I want to use the model in my template, I can only access the element ids, and not the data attributes like name (Remains empty when rendered).
<!-- ./app/templates/persons/index.hbs -->
{{#each model as |person index|}}
<li>
Person {{person.id}} {{index}}
{{person.name}}
{{#link-to 'persons.show' person }}
Link {{index}}
{{/link-to}}
</li>
{{/each}}
I am a bit at loss for why this happens. Am I doing something wrong?
The posted code is fine, the attributes I was missing in the templates was actually missing from the HTTP responses.

Ember: Error while processing route. Can't hit API

This code works (hardcoded):
import Ember from 'ember';
import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-route-mixin';
export default Ember.Route.extend(AuthenticatedRouteMixin, {
model() {
let stars = [
{
key: "johnlennon",
logoUrl: "https://www.images.com/johnl.png",
name: "John Lennon",
alive: false
}
}
}
});
When I do this, it doesn't (from API):
import Ember from 'ember';
import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-route-mixin';
import config from '../../../../../config/environment';
export default Ember.Route.extend(AuthenticatedRouteMixin, {
model() {
const token = this.get('session.data.authenticated.token');
return Ember.RSVP.hash({
stars: Ember.$.getJSON(Ember.$.getJSON(`${config.APP.starsAPI}/api/stars?authorizationToken=${token}`))
});
}
});
The error I receive:
jquery.js:9175 GET
http://localhost:4242/stars/948/connect/[object%20Object] 404 (Not
Found)
ember.debug.js:30291 Error while processing route:
stars.show.connect.stars.index
As you may have guessed, I need it to work from API. Why is that giving me the error?
It worked after this change:
import Ember from 'ember';
import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-route-mixin';
import config from '../../../../../config/environment';
export default Ember.Route.extend(AuthenticatedRouteMixin, {
model() {
const token = this.get('session.data.authenticated.token');
return Ember.$.getJSON(`${config.APP.starsApi}/api/stars?authorizationToken=${token}`).then(function(retVal){
return retVal;
});
}
});
Looks like you had chained `Ember.$.getJSON() methods.
return Ember.$.getJSON(`${config.APP.starsApi}/api/stars?authorizationToken=${token}`).then(function(retVal){
return retVal;
});
This should work fine

Why restore doesn't send event authenticationSucceeded when using ember-simple-auth?

I need to get current user when a session is authenticated. I have implemented the service currentUser
import Ember from 'ember';
const { inject: { service }, isEmpty, RSVP } = Ember;
export default Ember.Service.extend({
store: service(),
user: null,
load() {
return this.get('store').find('user', 'me').then((user) => {
this.set('user', user);
});
}
});
And I call it in route/application.js
import Ember from 'ember';
import ApplicationRouteMixin from 'ember-simple-auth/mixins/application-route-mixin';
export default Ember.Route.extend(ApplicationRouteMixin, {
session: Ember.inject.service(),
currentUser: Ember.inject.service(),
init: function(){
return this._super();
},
actions: {
invalidateSession() {
this.get('session').invalidate();
}
},
sessionAuthenticated() {
alert("sessionAuthenticated");
this._super(...arguments);
this._loadCurrentUser().catch(() => this.get('session').invalidate());
},
_loadCurrentUser() {
return this.get('currentUser').load();
}
});
When a user login or signup, the event authenticationSucceeded is called but when the session is restored in my authenticator, the event is not called. I need to call it because I need to reload user information.
I don't think that the sessionAuthenticated is triggered on restore. You need to load the user in your beforeModel hook.
// ...
beforeModel() {
return this._loadCurrentUser();
}
// ...
You can take a look at the official docs for setting the current user here

ember.js: Make AdminRouteMixin from AuthenticatedRouteMixin?

Is there a more elegant way to prevent unauthorized access to an admin-only route than writing this in all of my admin routes?
export default Ember.Route.extend(AuthenticatedRouteMixin, {
beforeModel: function(){
if(!this.get('session.secure.admin')) this.transitionTo("dashboard");
}
});
Perhaps it's possible to extend AuthenticatedRouteMixin itself to make this kind of check?
Thanks!
Why not just make the mixin?
import Ember from 'ember';
import AuthenticatedRouteMixin from 'wherever/it/is'.
const { Mixin } = Ember;
export default Mixin.create(AuthenticatedRouteMixin, {
beforeModel(){
if(!this.get('session.secure.admin')) {
this.transitionTo("dashboard");
}
}
})
And then import it in your routes:
import Ember from 'ember';
import AdminCheckMixin from 'yourApp/mixins/routes/admin-check';
const { Route } = Ember;
export default Route.extend(AdminCheckMixin);

Ember Simple Auth - setting multiple properties in a custom session

Following on from this question I am trying to set both the currentUser and the account properties in my custom session:
/app/sessions/custom.js
import Ember from 'ember';
import Session from 'simple-auth/session';
export default Session.extend({
currentUser: Ember.computed('secure.user_id', 'isAuthenticated', function() {
console.log('currentUser');
var userId = this.get('secure.user_id');
if (userId && this.get('isAuthenticated')) {
return this._store.find('user', userId);
}
}),
account: Ember.computed('currentUser', function() {
console.log('account');
this.get('currentUser').then(function(currentUser) {
return this._store.find('account', currentUser.get('account').id);
})
})
});
but for some reason the console.log('account'); is never called. I guess that this is because currentUser is a promise and thus hasn't yet resolved?
Should I return an Ember.RSVP.hash instead?