Ember model Not Bind Dynamically using Link-to - javascript

I created an ember demo,A parent view and it's child
this is the parent view
<h1>A list of Todo Tasks</h1>
<ul>
{{#each model as |todo|}}
<li>{{#link-to "todos.details" todo}}{{todo.desc}}{{/link-to}}</li>
{{/each}}
</ul>
{{outlet}}
and Its js login is
import Ember from 'ember';
export default Ember.Route.extend({
model (){
return [{
"id" : 1,
"desc" : "Try use ember"
},
{
"id" : 2,
"desc" : "Add it to github"
},
];
}
});
but when i use the link-to and navigate the data didn't show unless i refresh the page
This is the child view
<h2>The Details for <span style="color: green;">{{model.name}}</span> is : </h2>
{{#if model.error}}
<p>{{model.message}}</p>
{{else}}
<ul>
{{#each model.steps as |task|}}
<li>{{task.do}}</li>
{{/each}}
</ul>
{{/if}}
{{outlet}}
and its js logic
import Ember from 'ember';
export default Ember.Route.extend({
model(params){
if(params.id == "1"){
return {
name : "Ember SetUp",
steps : [{
id :1,
do : "Download Ember Cli"
},
{
id :2,
do : "Generate New Project"
},
{
id :3,
do : "Generate Pages&Routes"
}
]
};
}
else{
return {
error : true,
name : "Not Found",
message : "There is no task with this id"
}
}
}
});
iam using ember 2.5 and this is part of the router
this.route('todos', function() {
this.route('details',{path : "/:id"});
});

{{#link-to "todos.details" todo}}
Since you are providing the object todo, so it will not execute the model hook.
so try
{{#link-to "todos.details" todo.id}}
Refer here: https://guides.emberjs.com/v2.13.0/routing/specifying-a-routes-model/#toc_dynamic-models
Note: A route with a dynamic segment will always have its model hook
called when it is entered via the URL. If the route is entered through
a transition (e.g. when using the link-to Handlebars helper), and a
model context is provided (second argument to link-to), then the hook
is not executed. If an identifier (such as an id or slug) is provided
instead then the model hook will be executed.

Ack, OP of video here. Sorry about that. Small misspeaking on my part, I should address this in the comments of the video and try to revise that. Sorry for the confusion! D:

Related

pathFor cannot find route - Iron Router & Meteor

Iron Router cannot find a path that I'm pretty sure is defined correctly. The path name shows up as valid and exists in my meteor shell, but it returns as "undefined" in my Chrome console. Here's the template declaration:
<template name="vidPreview">
<div class="videoPreview">
<h2>{{title}}</h2>
Play
<p>Created At: {{createdAt}}</p>
{{#if isLive}}
<p>LIVE</p>
{{/if}}
<p>Viewers: {{uniqueViewers}}</p>
<p>Views: {{views}}</p>
<p>Location: {{location}}</p>
<ul>
{{#each genres}}
<li><p>{{this}}</p></li>
{{/each}}
</ul>
<p>Created by: {{creator}}</p>
</div>
</template>
And here's the route declaration:
Router.route('/video/:_id',{
name: 'singleVideo',
template: 'singleVideo',
layoutTemplate: 'singleVideo',
data: function(){
var currentVideo = this.params._id;
return Videos.findOne({ _id: currentVideo });
},
action: function(){
this.render('singleVideo');
}
});
There are no helpers operating on the vidPreview template. The data context is that of an individual Video object, and this template gets placed multiple times into a parent template. Help is greatly appreciated.
I thought the route name parameter in pathFor was positional, i.e.
{{pathFor 'singleVideo' _id=this._id }}
"We can pass data, query and hash options to the pathFor helper."
Try:
{{pathFor route='singleVideo' data={ _id: this._id} }}

Meteor.js Handlebar Returns different Text depending on current Route in Iron Router

When using Iron Router with Meteor.js 0.8.3, how can I have a text in a view template that changes depending on which route the user is on?
For example, if a user is at /profile, the text would be User Profile and if he is at / the text will be Home.
header.html
<template name="header">
<h1>{{ routeTitle }}</h1>
</template>
profile.html
<template name="profile">
{{> header}}
</template>
router.js
Router.map( function() {
this.route('index', {
path: '/',
template: 'index'
})
this.route('profile', {
path: '/profile/:_id',
template: 'profile',
data: function() { return Users.findOne(this.params._id); }
})
})
I personally store my own properties in the route options like this :
Router.map(function(){
this.route("index", {
// iron-router standard properties
path: "/",
// custom properties
title: "Home"
//
controller: "IndexController"
});
this.route("profile", {
path: "/profile/:_id",
title: "User profile",
controller: "ProfileController"
});
});
Then I extend the Router with a set of utilities functions to access the current route.
_.extend(Router,{
currentRoute:function(){
return this.current()?this.current().route:"";
}
});
UI.registerHelper("currentRoute",Router.currentRoute.bind(Router));
Using these utilities, you can call Router.currentRoute() in JS which happens to be a reactive data source too, as it acts as a wrapper for Router.current().
Use Router.currentRoute() && Router.currentRoute().options.title to check whether there is a current route and fetch the title you declared in the route definition.
In templates you can use {{currentRoute.options.title}} to fetch the current title, this is helpful when working with iron-router layouts.
If you want to get more specific you can even mimic the Router.path and pathFor helper behavior :
_.extend(Router,{
title:function(routeName){
return this.routes[routeName] && this.routes[routeName].options.title;
}
});
UI.registerHelper("titleFor",Router.title.bind(Router));
Now you can call Router.title("index") in JS and {{titleFor "index"}} in templates.
You can even get as far as having a dedicated helper for the current route title, as you suggested in your question :
UI.registerHelper("currentRouteTitle",function(){
return Router.currentRoute() && Router.currentRoute().options.title;
});
You can achieve this very easily with data param of the path:
Router.map(function() {
this.route('...', {
...
data: function() {
return {
importantText: 'User Profile',
};
},
});
});
Now use it as any other data object in your rendered template, layout template, or any of the templates rendered to named area:
{{importantText}}

How to affect state of ObjectController from its ArrayController in ember.js

I am still trying to understand how to properly structure an ember.js application. So, this may be a systemic issue with the way I am trying to solve this. That being said, I am going to try asking the same question a couple different ways ...
In the code example below, when a record is created, how can I get it to be added to the list with the isEditing property set to true?
Can I access to a specific object controller from its array controller?
Each task has a view state and an edit state. When a new task is created, how can I have it initially appear in the edit state?
App.TasksController = Ember.ArrayController.extend({
actions: {
createTask: function(){
var task = this.store.createRecord('task');
task.save();
}
}
});
App.TaskController = Ember.ObjectController.extend({
isEditing: false,
actions: {
toggleEditing: function(task) {
if(this.isEditing){
task.save();
}
this.set('isEditing', ! this.isEditing );
}
}
});
<script type="text/x-handlebars" data-template-name="tasks">
<ul>
{{#each task in controller}}
{{render "task" task}}
{{/each}}
<li {{action "createTask"}} >
New Task
</li>
</ul>
</script>
<script type="text/x-handlebars" data-template-name="task">
<li {{action "toggleEditing" task on="doubleClick"}} >
{{#if isEditing }}
{{textarea value=title cols="80" rows="6"}}
{{else}}
{{title}}
{{/if}}
</li>
</script>
Set the property on the model.
You don't have to define the property as an attr on the model (which means it won't send it up to the server on save etc), but you can set the property on the model.
Or you can do it based on the currentState of the model. (click go to orders, then add orders)
http://emberjs.jsbin.com/AvOYIwE/4/edit
App.OrderController = Em.ObjectController.extend({
_editing: false,
editing: function(){
return this.get('_editing') || (this.get('model.currentState.stateName') == 'root.loaded.created.uncommitted');
}.property('model.currentState.stateName', '_editing'),
actions: {
stopEditing: function(){
// blow away the computed property and just set it to true
this.set('editing', false);
},
startEditing: function(){
this.set('editing', true);
},
}
});

Seo routes with ember serializer

Im following the example emberjs guides
...
this.route('author', { path: '/author/:post_userName' });
...
App.PostsAuthorRoute = Ember.Route.extend({
model: function(params) {
return App.Post.find({userName : params.userName});
},
serialize:function(model) {
return { post_userName: model.get('userName')};
}
});
Then here is the link to
Author {{#linkTo 'posts.author' post }} {{post.userName }} {{/linkTo}}
The fun is when I click on the link I get a routing error
Error while loading route: TypeError {}
Uncaught TypeError: Object [Object Object] has no method 'slice'
But when I reload the page, the full data appears.
How can I solve the routing error, really I don't understand why I get the error and is solved on reload the page
Here is the jsbin of a similar case.
http://jsbin.com/aZIXaYo/31/edit
The problem is with the object you're passing to your link-to. You're doing this :
Author {{#linkTo 'posts.author' post }} {{post.userName }} {{/linkTo}}
which passes, a Post to the author route. Passing a model to link-to causes the model hook on the route to be skipped and the passed model is used instead. When you hit reload, the model hook is executed and the model for PostsAuthor route is set to be a collection of Post objects, and then things work as expected.
To do things The Ember Way (TM), you'd want to have an Author model that was related to your Post model. Then you'd have an AuthorRoute and AuthorController that needs a PostsController. In your link you'd pass post.author, and then use the setupController hook to prime the collection for the PostsController. Something like this:
App.Post = DS.Model.extend({
author : DS.belongsTo('post'),
title : DS.attr('string')
});
App.Author = DS.Model.extend({
name : DS.attr('string'),
userName : DS.attr('string')
});
App.AuthorRoute = DS.Route.extend({
model : function(){ // not called when the author is passed in to #link-to
return this.store.find('author',{userName : params.post_userName})
},
setupController : function(controller,model){
this._super(controller,model);
this.controllerFor('posts').set('content', this.store.find('post',{userName : model.userName}))
}
});
App.AuthorController = Ember.ObjectController.extend({
needs : ['posts']
});
App.PostsController = Ember.ArrayController.extend({
sortProperties : ['name']
});
Then the template :
Author {{#linkTo 'posts.author' post.author }} {{post.author.name }} {{/linkTo}}

Load data from controller in ember.js

I want to implement a system that shows me the newest posts. For this I do not want to use the index action from the user as this is already taken for another post function but a "newest" action. It is showed on the index route with a {{ render "postNewest" }} call. I would prefer to load the data in the PostNewestController or PostNewestView instead of the route for abstraction reasons.
I tried two ideas to achieve this, but none worked so far:
create a custom adapter and add a findNewest() method: the findNewest() method is sadly not found when trying to call in the init method of the controller.
write the request directly into the init method and then update with store.loadMany(payload): data is successful request. However, I do not know how to access the data from the template and set the content of the controller.
Is there any way for this?
EDIT:
Here is the source code to better understand the problem:
PostModel.js
App.Post.reopenClass({
stream: function(items) {
var result = Ember.ArrayProxy.create({ content: [] });
var items = [];
$.getJSON("/api/v1/post/stream?auth_token=" + App.Auth.get("authToken"), function(payload) {
result.set('content', payload.posts);
});
return result;
}
});
PostStreamController.js
App.PostStreamController = Ember.ArrayController.extend({
init: function() {
this.set("content", App.Post.stream());
},
});
index.hbs
{{# if App.Auth.signedIn}}
{{ render "dashboard" }}
{{else}}
{{ render "GuestHeader" }}
{{/if}}
{{ render "postStream" }}
postStream.hbs
{{#each post in model}}
<li>{{#linkTo 'post.show' post data-toggle="tooltip"}}{{post.name}}{{/linkTo}}</li>
{{else}}
Nothing's there!
{{/each}}
PostShowRoute.js
App.PostShowRoute = Ember.Route.extend({
model: function(params) {
return App.Post.find(params.post_id);
},
setupController: function(controller, model) {
controller.set('content', model);
},
});
I Had this issue too. Just add init in your controller, and define the model you want to get there.
In your Controller
App.PostRecentController = Ember.ArrayController.extend({
init: function() {
return this.set('content', App.Post.find({
recent: true
}));
}
});
In your template
{{#each post in content}}
{{post.body}}
{{/each}}
I would recommend you check EMBER EXTENSION, it will give you a good idea of the naming, and see if everything is missing.
I figured out the problem. The Post model has a belongsTo relationship to another model. This relationship is not loaded by Ember so in the stream() method I have to load this manually. Then everything works as expected.

Categories

Resources