I'm using Ember for the front end and I am doing basic testing to see if I can properly render my data before adding components. I have two resources 'Topics' and 'Ratings' and I have added both a route and a model hook for these resources. When I type http://localhost:4200/topics, I am able to see all of the topics being rendered on the template. However, when I type http://localhost:4200/ratings, I receive an error on the console saying:
ember.debug.js:32096TypeError: Cannot read property 'some' of undefined
at error (route.js:21)
at Object.triggerEvent (ember.debug.js:28580)
at Object.trigger (ember.debug.js:53473)
at Object.Transition.trigger (ember.debug.js:53287)
at ember.debug.js:53107
at tryCatch (ember.debug.js:53806)
at invokeCallback (ember.debug.js:53821)
at publish (ember.debug.js:53789)
at publishRejection (ember.debug.js:53724)
at ember.debug.js:32054
Which is strange because in my rails console, I am receiving a HTTP: 200 response. Is there some error within the code of my routes? I made sure to mirror ratings similar to topics. Or is this an association issue? Both a USER and a TOPIC have many ratings. I provided snippets of my code below:
Application Route:
import Ember from 'ember';
export default Ember.Route.extend({
auth: Ember.inject.service(),
flashMessages: Ember.inject.service(),
actions: {
signOut () {
this.get('auth').signOut()
.then(() => this.transitionTo('sign-in'))
.then(() => {
this.get('flashMessages').warning('You have been signed out.');
})
.catch(() => {
this.get('flashMessages')
.danger('There was a problem. Are you sure you\'re signed-in?');
});
this.store.unloadAll();
},
error (reason) {
let unauthorized = reason.errors.some((error) =>
error.status === '401'
);
if (unauthorized) {
this.get('flashMessages')
.danger('You must be authenticated to access this page.');
this.transitionTo('/sign-in');
} else {
this.get('flashMessages')
.danger('There was a problem. Please try again.');
}
return false;
},
},
});
Rating Model:
import Model from 'ember-data/model';
import attr from 'ember-data/attr';
import { belongsTo } from 'ember-data/relationships';
export default Model.extend({
score: attr('number'),
user: belongsTo('user'),
topic: belongsTo('topic')
});
Rating Route:
import Ember from 'ember';
export default Ember.Route.extend({
model(params) {
return this.get('store').findRecord('rating', params.id);
},
});
```
Ratings Route:
import Ember from 'ember';
export default Ember.Route.extend({
model() {
return this.get('store').findAll('rating');
},
});
Router:
import Ember from 'ember';
import config from './config/environment';
const Router = Ember.Router.extend({
location: config.locationType,
});
Router.map(function () {
this.route('sign-up');
this.route('sign-in');
this.route('change-password');
this.route('users');
this.route('topics');
this.route('topic', { path: '/topics/:id'});
this.route('ratings');
this.route('rating', { path: '/ratings/:id'});
// Custom route in topics controller that will call NYT API or generate random-show
//topic. This is a GET request essentially
this.route('random-show');
});
export default Router;
SOLVED! Read the DOCS, and used EXPLICIT INVERSNESS:
https://guides.emberjs.com/v2.5.0/models/relationships/
Apparently, Ember needs help understanding when you have multiple has Many or Belong to for the same type.
Related
I'm working on a project that uses Rails and React, with react-router version 4.2.0 and react-router-redux 5.0.0-alpha.9. It's the first time I use React and I'm having trouble routing.
In my routes.jsx file I have the following path:
const routes = [
{ path: /\/events\/(\d)$/, action: () => <EventForm /> },
];
When I type http://localhost:3000/events/2 in my browser I get the content back.
I want to modify my route so this link won't be valid unless there's a userToken appended to it as a query string. (I know this is not the best security practice but it's valid for the purpose of this project)
For example, the following link http://localhost:3000/events/2 should not work, but the link http://localhost:3000/events/2?userToken=abc should work.
I tried these options but it didn't work:
{ path: /\/events\/(\d)\?userToken\=(\w)$/, action: () => <EventForm /> }
{ path: /\/events\/(\d)\?userToken=[\w]$/, action: () => <EventForm /> }
Thanks!
One way is to check url param in componentDidMount lifecycle method of EventForm:
class EventForm extends Component{
componentDidMount(){
const {location, history} = this.props // these are by design in props when using react-router
if(!location.query.userToken){
history.push('/login') // or whatever route
}
}
render(){
return (<div>...</div>)
}
}
export default EventForm
I'm trying to post a data(book) to my Rails Api using Vue JS and Axios. Here's the code from my BookList component:
<script>
import BookForm from './BookForm';
export default {
name: 'hello',
data(){
return{
books: []
}
},
mounted() {
axios.get("http://localhost:3000/api/v1/books")
.then(response => {this.books = response.data})
},
components:{
BookForm
},
methods:{
onClickForm(book){
console.log(book)
this.books.push(book)
axios.post("http://localhost:3000/api/v1/books",{book})
.then(function (response) {
console.log(response);
})
console.log('Book created')
}
}
}
</script>
I am able to post the book object but I get an error from the console. It seems my axios post request is not done correctly. Please note that I am sending the book object from my BookForm component emitting an event connected with the onClickForm method. What's wrong in my method? Thanks
This the error I am getting from the console:
This is the message that i get from the rails api server :
The book is created but I get a 500 internal error. Any help? Thanks
So I have a Rails API and an Ember application. At the moment, my Ember has a login.hbs template and a login.js controller.
I have done a ember install ember-ajax (https://github.com/ember-cli/ember-ajax).
On entering an email and password, I click on the login button which calls my login.js action loginClicked()
I have the following in my login controller:
// login.js controller
import Ember from 'ember';
export default Ember.Controller.extend({
email: '',
password: '',
actions: {
loginClicked() {
// alert("email: " + this.get('email') + "\npassword: " + this.get('password'));
let params = {
email: this.get('email'),
password: this.get('password')
};
post('/authenticate', {
params: params
});
}
}
});
In my login.js route handler, I have injected the ember-ajax service:
// login.js route handler
import Ember from 'ember';
export default Ember.Route.extend({
ajax: Ember.inject.service()
});
The problem is, my Mac terminal console is outputting an error saying:
controllers/login.js: line 16, col 7, 'post' is not defined.
I have also tried injecting the ember-ajax service into my controller but it made no difference.
Am I doing something wrong ?
Everything is described into the ember-ajax github page https://github.com/ember-cli/ember-ajax
export default Ember.Controller.extend({
ajax: Ember.inject.service(),
actions: {
loginClicked() {
let params = {
email: this.get('email'),
password: this.get('password')
};
return this.get('ajax').request('/authenticate', {
method: 'POST',
data: params
});
}
}
});
Basically, to access any property of your controller (component, ...) in ember, you need to get it using this.get('propertyName').
Here you need to use the request method of the ajax property (the injected service).
I'm working on my second Ember project, and first using Rails on the backend. I'm struggling with loading associated data through my API in a nested route. The association is simple: a folder has many media_files in my backend (I'm aware snake case is against convention but trying to work around it).
When I do the following, I get the correctly nested route (folders/show/media_files) and no complaints when loading the template, but the data is empty in the console and doesn't render in the template.
Thank you for your time.
Here is my routing:
Router.map(function() {
this.route('folders', function(){
this.route('show', {
path: ':folder_id'
}, function() {
this.route('media_files', {resetNamespace: true}, function (){
});
});
});
});
Here are my associations:
Folder:
import DS from 'ember-data';
export default DS.Model.extend({
name: DS.attr('string'),
media_files: DS.hasMany('media_file')
});
Media Files:
import DS from 'ember-data';
export default DS.Model.extend({
name: DS.attr('string'),
duration: DS.attr('number'),
createdAt: DS.attr('date'),
folder: DS.belongsTo('folder')
});
Here is the call to the media files index:
import Ember from 'ember';
export default Ember.Route.extend({
model: function(){
return this.modelFor("folders/show").get("media_files");
}
});
My URL is folders/folder_id/media_files, same as in my API. The JSON there looks like this:
{
media_files: [
{
id: 513009,
url: null,
project_id: 999,
batch_id: 1268,
duration: 30556,
rush: false.....
This is how I do my routes in backbonejs where the routing and its params are obtained first before deciding which external template to call. I find this is quite flexible.
var Router = Backbone.Router.extend({
routes: {
//'': 'renderBasic',
':module/:method/': 'renderDynamicViewPageBasic',
':module/:branch/:method/': 'renderDynamicViewPageBranch',
':module/:branch/:method/set:setnumber/page:pagenumber/': 'renderDynamicViewPagePager',
':module/:branch/:method?set=:setnumber&page=:pagenumber': 'renderDynamicViewPagePager'
},
renderDynamicViewPageBasic: function (module,method) {
$(el).html(Handlebars.getTemplate('template1')(data));
},
renderDynamicViewPageBranch: function (module,branch,method) {
$(el).html(Handlebars.getTemplate('template2')(data));
},
renderDynamicViewPagePager: function (module,branch,method,setnumber,pagenumber) {
$(el).html(Handlebars.getTemplate('template3')(data));
}
});
How about in emberjs, can I do the same - do the rout and get its params afirst before deciding which external template to call?
I read the documentation and tested it. It seems to be less flexible - for instance,
App.Router.map(function() {
this.route("about", { path: "/about" });
this.route("favorites", { path: "/favs" });
});
Is it possible to get the route and params and then the controller before getting the template?
if not, it seems to be the same as case using Angularjs which I finally decided not to use it because it gets the template first before sorting out the params.
You can define the template "post params" in EmberJs using the renderTemplate hook, where you can customize which template you'd like to use.
http://emberjs.jsbin.com/oXUqUJAh/1/edit
App.Router.map(function() {
this.route('apple', {path: 'apple/:id'});
});
App.AppleRoute = Ember.Route.extend({
model: function(params) {
return {coolProperty: params.id};
},
renderTemplate: function(controller, model) {
// send in the template name
this.render(model.coolProperty);
}
});
You can pass a function together with $route params to get customized result in angularjs actually.
template: function($params) {
return app.$templateCache.get($params); // or make template yourself from another source
}