ember has many with async true - javascript

I has many relation in my ember app but it is not working recursively.
here is my model.
-->tree.js
export default DS.Model.extend({
parent : DS.attr(),
parentId : DS.attr('number', {defaultValue: "0"}),
childrens: DS.hasMany('menu', {async:true}),
name : DS.attr(),
});
route code-->
export default Ember.Route.extend({
model: function() {
return this.store.findAll('treeview');
}
});
hbs-->>
{{#each model as |tree|}}
<div class="col-lg-12">
{{#unless tree.parentId}}
{{tree.name}}
{{#if tree.childrens}}
{{#each tree.childrens as |childmenu|}}
<div class="col-lg-12" style="margin-left:30px;">
{{sub-tree-view tree = tree}}
</div>
{{/each}}
{{/if}}
{{/unless}}
</div>
{{/each}}
sub-tree-view component js file -->
showRecord:function(){
let self = this;
let tree = self.get('tree');
var test = tree.get('childrens'); }.property(),
But it not calling the model again with children id .
With hasmany relation it should call the menu model recursively but it is not making the request again. How to deal with the has many relationship data.?

Related

Toggle row independently of others in an {{#each}} - Ember

I've got this chunk of code in my controller to output everything I'd like to in the first row. The second row is going to be available upon a click action. However, I'm trying to make it so that when I click any row shown, it'll only display the 2nd row that given row. Not the 2nd row of all the others.
This is in my template.
{{#each chosenSomething as |something|}}
<tr class='main' {{action 'toggleHelp'}}>
<td>{{something.this}}</td>
<td>{{something.that}}</td>
<td>{{something.hey}}</td>
<td>{{something.you}}</td>
</tr>
{{#if isDisplay}}
<tr class='help'>
<td class='instruction'></td>
<td class='video'></td>
</tr>
{{/if}}
{{/each}}
This is my JS for the action.
toggleHelp() {
this.toggleProperty('isDisplay');
},
I know how I would approach this using jQuery, but I'd like to know the Ember way of doing such action. I thought about including index, but unsure how it should be written.
I would suggest making a component and handing the toggle within.
https://ember-twiddle.com/e6ccad3d2ffdc4a9d627db12a1317fa5?openFiles=templates.components.toggle-thing.hbs%2Ctemplates.components.toggle-thing.hbs
// toggle-thing.hbs
<header {{action 'toggleAnswer'}}>
{{data.question}}
</header>
{{#if open}}
<footer>
{{data.answer}}
</footer>
{{/if}}
// toggle-thing.js
import Ember from 'ember';
export default Ember.Component.extend({
// tagName: 'tr', // or whatever if you like
// classNames: ['thing', 'row', 'etc'], // smooth out the template a bit later...
open: false, // default
actions: {
toggleAnswer() {
this.toggleProperty('open');
console.log( this.get('open') );
},
},
});
// application.hbs or wherever you want to list the things
<ul class='thing-list'>
{{#each model as |thing|}}
<li class='thing'>
{{toggle-thing data=thing}}
</li>
{{/each}}
</ul>
has a 'thing' model and is pulling in some question answers to the model hook for example.
import Ember from 'ember';
var data = [
{
question: "How to be funny",
answer: "Stand on your head",
},
{
question: "How to be smart",
answer: "Just listen more often.",
},
];
export default Ember.Route.extend({
model() {
return data;
},
});
The Ember guide has a toggle example: https://guides.emberjs.com/v2.13.0/tutorial/simple-component/
Augment each element of chosenSomething to include the open/close state.
You'll then be able to have:
{{#each chosenSomething as |something|}}
<tr class='main' {{action 'toggleHelp' something}}>
<td>{{something.this}}</td>
<td>{{something.that}}</td>
<td>{{something.hey}}</td>
<td>{{something.you}}</td>
</tr>
{{#if something.isDisplay}}
<tr class='help'>
<td class='instruction'></td>
<td class='video'></td>
</tr>
{{/if}}
{{/each}}
and the JS:
toggleHelp(something) {
Ember.set(something, 'isDisplay', !something.isDisplay);
}
If you don't want to modify the original data, you can have a computed property generate the appropriate data such as:
chosenSomethingWithState() {
return (this.get('chosenSomething') || []).map((item)=>{isDisplay:false, item})
}.property('chosenSomething')
and adjust the template accordingly

How to pass selected value between routes?

I am quite new to the EmberJS.
This is my model: book.js
import DS from 'ember-data';
export default DS.Model.extend({
title: DS.attr('string'),
author: DS.attr('string'),
picture: DS.attr('string'),
buyer: DS.attr('string'),
bought: DS.attr('boolean', { defaultValue: false }),
createdAt: DS.attr('date', { defaultValue() { return new Date(); } })
});
I have the following route:
Books.js
import Ember from 'ember';
export default Ember.Route.extend({
model: function(){
return this.store.findAll('book');
}
});
and a bit from corresponding books.hbs
{{#each model as |book|}}
<div class="book-container col-xs-12 col-sm-6 col-md-4">
<div class="card">
<div class="wrapper">
<div class="details col-md-12">
<h3 class="product-title">Title {{book.title}}</h3>
<p class="product-description">Author:{{book.author}}</p>
{{#link-to 'books.give' }} Buy {{/link-to}}
</div>
</div>
</div>
</div>
{{/each}}
This code returns all the books that I currently store in the app.
The idea is to get selected Book object from books.hbs and display it in give.hbs.
I wanted to use this line
{{#link-to 'books.give' }} Buy {{/link-to}}
to pass single a single book from books.hbs to give.hbs, but I don't know how to do that and if its the way to go..
In gift.hbs I partially invented a very inefficient way of doing it by looping all the books again and if the title is a match then display it...
{{#each model as |book|}}
{{#if (eq book.title "Harry Potter")}}
<h2><b>{{book.title}}</b></h2>
{{/if}}
{{/each}}
Obviously the "Harry Potter" string is hard-coded but it could have been passed from books.hbs and that would do the trick since my data is relatively small.
It depends on how do you want to represent URL.
if it's books/give/bookId => then go for dynamic segments
if its books/give?bookId=1 => then go for query params implementation
Inside books.give route get the particular book record using findRecord and use it.

Ember model data not showing up in template

I am building my first ember application and I can't get the model data to go from my songs modal to my songs template...
router.js
import Ember from 'ember';
import config from './config/environment';
const Router = Ember.Router.extend({
location: config.locationType
});
Router.map(function() {
this.route('songs');
this.route('song', {path: 'songs/:song_trackId'});
});
export default Router;
Here is my songs.js which displays properly
<div>songs</div>
{{#each model as |song|}}
{{#link-to 'song' song}}
<img height='100px' width='100px' src = '{{song.artworkUrl100}}'>
<div>{{song.trackId}}</div>
{{/link-to}}
{{/each}}
{{outlet}}
Here is my songs route..
import Ember from 'ember';
var data = {
"results" : [
{"wrapperType":"track", "kind":"song", "artistId":148662, "collectionId":528436018, "trackId":528437613,......
.
.
.
]}
export default Ember.Route.extend({
model: function(){
return data.results;
}
});
Lastly...the song template where the data should go when the user clicks
<div>HI</div>
<div> ArtistId: {{artistId}} </div>
<div> trackId: {{trackId}} </div>
<div> Kind: {{kind}} </div>
{{outlet}}
I dont think the link-to is setup improperly. Am I referencing the dynamic song incorrectly in the router?
I didn't define a song route model....
All I needed to do is set up a model in the song route as follows..
I left out the data object but in general I had to pass in the param and then grab it with the model here to find the object I was looking for with a filter
export default Ember.Route.extend({
model: function(params) {
var index = data.results.filter(function(obj){
return obj.trackId == params.song_trackId
})
var values = index[0]
return values
}
});

How render a route relevant subheader with meteor blaze?

The end result of all of what I am about to go over is the subheader is not rendering on screen like i want it to.
Currently there is a mongo collection subheader with a category field and a texth field.
Subheader = new Mongo.Collection('subheader');
Meteor.methods({
subheaderInsert: function(subheaderIdAttributes) {
check(String);
check(subheaderIdAttributes, {
texth: String,
category: String
});
var subheaderId = _.extend(postAttributes, {
submitted: new Date()
});
var subheaderId = SubheaderId.insert(subheader);
return {
_id: subheaderId
};
}
});
There is a route that subscribes to the subheader and other page data.
Router.route('/', {
name: 'home',
controller: MissionstatementpostController,
waitOn:function () {
return Meteor.subscribe('subheader', 'home');
}
});
The publish function appears to work fine.
Meteor.publish('subheader', function(cat) {
return Subheader.find({category: cat});
});
The correct doc from the mongodb collection is reaching the client. this can be seen by
Subheader.findOne(); output Object {_id: "NPo5cwqgjYY6i9rtx", texth: "ex text", category: "home"}
The problem starts here
The template loaded by the Controller in this case MissionstatementpostController is postlist
<template name="postsList">
<div class="posts page">
{{> subheader}}
<div class="wrapper">
{{#each posts}}
{{> postItem}}
{{/each}}
</div>
{{#if nextPath}}
<a class="load-more" href="{{nextPath}}">Load more</a>
{{else}}
{{#unless ready}}
{{> spinner}}
{{/unless}}
{{/if}}
</div>
</template>
Here is the subheader template
<template name="subheader">
<div class="container">
<p>{{{texth}}}</p>
</div>
</template>
So what did I mess-up?
thanks
you must create a template helper for your subheader template. To return just the texth field, the helper will be like this.
Template.subheader.helpers({
texth: function() {
var sh = Subheader.findOne();
return sh && sh.texth;
}
});
You can return the whole document and use the #with helper inside the template.
Template.subheader.helpers({
subh: function() {
return Subheader.findOne();
}
});
<template name="subheader">
{{#with subh}}
<div class="container">
<p>{{{texth}}}</p>
</div>
{{/with}}
</template>
You can find more info about template helpers on Meteor Docs.

EmberJS: Insert component dynamically

Got following components:
App.ParentComponent = Ember.Component.extend({
child: '',
yieldTemplateName: 'empty_by_default',
setup: function(){
//append here child compoment
}.on('didInsertElement')
});
App.ChildComponent = Ember.Component.extend({
templateName: 'some_location',
actions:{
//whatever
}
});
What am I wondering if is possible to add child component into parent's at any render status and based on a parameter?
So I call, for example:
{{parent child="child"}}
And it eventually renders:
<div !-- parent -- >
<div !-- child -- > </div>
</div>
App.ParentComponent = Ember.Component.extend({
child: null,
hasChild: Em.computed.notEmpty('child')
});
// parent template
{{#if hasChild}}
{{component child}}
{{/if}}
// another template
{{parent child="child"}} {{!-- displays ChildComponent --}}
Note: The component helper will be available in Ember 1.11. If you are using an earlier version, you can use the ember-dynamic-component addon.

Categories