How do I work with handlebars (EmberJS) - javascript

So when I click a button on my template it is supposed to change a value and display a list of records on the screen. This is not happening. What am I doing wrong? Below is the code for my controller, model, template and route.
Controller:
import Ember from 'ember';
export default Ember.Controller.extend({
usernameIn: '',
passwordIn: '',
found: '',
display: false,
actions:{
renderNotes(){
this.display = true;
}
}
});
Route:
import Ember from 'ember';
export default Ember.Route.extend({
model()
{
return this.store.findAll('note');
}
});
Template:
<h1>Login:</h1>
<h3>Username:</h3>{{input type="text" value = keyInput size="50"}}
<h3>Password:</h3>{{input type="text" value = keyInput size="50"}}
<br>
<br>
<button{{action 'renderNotes'}}>Submit</button>
{{#if display}}
<thead>
<tr>
<th>Username</th>
<th>Note</th>
</tr>
</thead>
<tbody>
{{#each model as |found|}}
<tr>
<th>{{found.username}}</th>
<td>{{found.note}}</td>
</tr>
{{/each}}
</tbody>
{{/if}}
{{outlet}}
Model:
import DS from 'ember-data';
export default DS.Model.extend({
note: DS.attr('string'),
username: DS.attr('string'),
password: DS.attr('string')
});

For your very simple use-case, rather that creating an action code in component.js, you can easily do this in the template.hbs if you're using Ember 2+. Here's how:
<button onclick={{action (mut display) true)}}>Submit</button>

You have to use 'set' for setting ember property
renderNotes(){
this.set('display', true);
}

Related

ember has many with async true

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.?

How to disable autofill on ember form field

I have a form for updating the details of alumni in ember using RESTful api. Is it possible to prevent the form from auto filling the data I previously entered in the form corresponding to another record in the model?
I have these codes in my update route directory(I am using pod-structure):
controller.js
# app/alumnis/update/controller.js
import Controller from '#ember/controller';
import { get, set } from '#ember/object';
export default Controller.extend({
firstName: null,
actions: {
updateAlumni(value) {
let firstName = get(this, 'firstName');
if(firstName) {
firstName = firstName.charAt(0).toUpperCase() + firstName.slice(1).toLowerCase();
this.get('store').findRecord('alumni', value).then(function(alumni) {
alumni.set('firstName', firstName);
alumni.save();
});
}
this.transitionToRoute('alumnis.show', value)
},
},
});
route.js
# app/alumnis/update/route.js
import Route from '#ember/routing/route';
import { set } from '#ember/object';
export default Route.extend({
model(params) {
return this.store.findRecord('alumni', params.id);
},
setupController(controller, model) {
set(controller, 'alumni', model);
}
});
template.hbs
# app/alumnis/update/template.hbs
<form class="alumniForm" {{action "updateAlumni" on="submit"}}>
<div class="form-group">
<h3>First Name : {{input name="firstName" type="text" value=firstName placeholder=alumni.firstName autocomplete="off"}}</h3>
</div>
<button class="btn btn-primary" {{action "updateAlumni" alumni.id}}>Submit</button>
</form>
router.js
# 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('alumnis', function() {
this.route('show', {path: '/:id'});
this.route('add', {path: '/add'});
this.route('update', {path: '/:id/update'});
});
});
export default Router;
On the first rendering of update route after every reloading, no form fields are filled automatically. But, once we enter data to the firstName input field, it is rendered to form field in update page of any other record in the model alumni.
Properties that are set in a controller in ember will remain set when you re-navigate to the page.
The logic you've shown, leads me to believe you don't even need the controller. You are modifying a model property, saving it and transitioning.
You were doing a round-about way of updating the record, The alumni record was your model, yet you were trying to re-fetch it from the store.
route.js
# app/alumnis/update/route.js
import Route from '#ember/routing/route';
import { set,get } from '#ember/object';
export default Route.extend({
model(params) {
return this.store.findRecord('alumni', params.id);
},
updateAlumni() {
let changedAttrs = get(this, 'model').changedAttributes();
if (changedAttrs.firstName) {
let firstName = get(this, 'model.firstName').toLowerCase().capitalize();
set('model.firstName', firstName);
}
get(this,'model').save()
this.transitionToRoute('alumnis.show', get(this,'model'))
}
});
template.hbs
# app/alumnis/update/template.hbs
<form class="alumniForm" {{action "updateAlumni" on="submit"}}>
<div class="form-group">
<h3>First Name : {{input name="firstName" type="text" value=model.firstName placeholder=alumni.firstName autocomplete="off"}}</h3>
</div>
<button class="btn btn-primary" {{action "updateAlumni"}}>Submit</button>
</form>
I was able to resolve the issue by changing the below codes:
controller.js
# app/alumnis/update/controller.js
import Controller from '#ember/controller';
import { get, set } from '#ember/object';
export default Controller.extend({
firstName: null,
actions: {
updateAlumni(value) {
let alumni = get(this, 'alumni');
let changedAttrs = alumni.changedAttributes();
if(changedAttrs.firstName) {
let firstName = alumni.firstName.toLowerCase().capitalize();
alumni.set('firstName', firstName);
alumni.save()
}
this.transitionToRoute('alumnis.show', value)
},
},
});
template.hbs
# app/alumnis/update/template.hbs
<form class="alumniForm" autocomplete="off" {{action "updateAlumni" on="submit"}}>
<div class="form-group">
<h3>First Name : {{input name="firstName" type="text" value=alumni.firstName}}</h3>
</div>
<button class="btn btn-primary" {{action "updateAlumni" alumni.id}}>Submit</button>
</form>
No change in app/alumnis/update/route.js

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.

Application in Ember doesn't recognize the model so it ends up with index data being null

I started an adventure with Ember a few weeks ago.
I have solid progress thanks to docs and example around the internet.
Sadly I hit a solid wall with this one as have almost copy-pasted models out of which most work and one and only one does not.
The error that I see in Inspector is:
Encountered a resource object with type "series", but no model was found for model name "series" (resolved model name using 'my-app#serializer:-json-api:.modelNameFromPayloadKey("series"))
Error while processing route: serie.index data is null...
I'm using mirage fixtures with success
// mirage/fixtures/files.js
export default [
{duration:'1',filename:'1.mkv',size:'1',id:'1',url:'dl/1.mkv'},
{duration:'2',filename:'2.mkv',size:'2',id:'2',url:'dl/2.mkv'}
];
// mirage/fixtures/series.js
export default [
{type:'show',title:'ser1',summary:'123',id:'11'},
{type:'show',title:'ser2',summary:'234',id:'12'}
];
Both use the same model for mirage
// mirage/model/file.js
// mirage/model/serie.js
import { Model } from 'ember-cli-mirage';
export default Model.extend({
});
I load fixtures this way:
// mirage/scenarios/default.js
export default function(server) {
server.loadFixtures();
}
And serializer is set on mirage this way:
// mirage/serializers/application.js
import { JSONAPISerializer } from 'ember-cli-mirage';
export default JSONAPISerializer.extend({
});
the only thing that I added to the config is
// added to mirage/config.js
this.namespace = 'api';
this.get('/series');
this.get('/series/:id');
this.get('/files');
this.get('/files/:id');
There is nothing more to do with mirage so let's move onto ember.
// app/adapters/application.js
application.js
import DS from 'ember-data';
export default DS.JSONAPIAdapter.extend({
namespace: 'api'
});
Both use the same component
// app/components/file-view.js
// app/components/serie-view.js
import Ember from 'ember';
export default Ember.Component.extend({
});
Models are defined this way:
// app/models/file.js
import DS from 'ember-data';
export default DS.Model.extend({
filename: DS.attr(),
url: DS.attr(),
art: DS.attr()
});
// app/models/serie.js
import DS from 'ember-data';
export default DS.Model.extend({
title: DS.attr(),
type: DS.attr(),
summary: DS.attr()
});
// app/router.js
import Ember from 'ember';
import config from './config/environment';
const Router = Ember.Router.extend({
location: config.locationType,
rootURL: config.rootURL
});
Router.map(function() {
this.route('serie', function() {
this.route('show');
});
this.route('file', function() {
this.route('show');
});
});
export default Router;
Routes are almost identical
// app/routes/file.js
import Ember from 'ember';
export default Ember.Route.extend({
model() {
return this.get('store').findAll('file');
}
});
// app/routes/serie.js
import Ember from 'ember';
export default Ember.Route.extend({
model() {
return this.get('store').findAll('serie');
}
});
Same goes for the templates
// app/templates/file.hbs
<h2>Files</h2>
{{#each model as |fileUnit|}}
{{file-view file=fileUnit}}
{{/each}}
{{outlet}}
// app/templates/serie.hbs
<h2>Series</h2>
{{#each model as |serieUnit|}}
{{serie-view serie=serieUnit}}
{{/each}}
{{outlet}}
And last are the component templates:
// app/templates/components/file-view.js
<div>
<img src="cover.jpg" width=200 hight=200 alt="">
<h3>{{file.filename}} id: {{file.id}}</h3>
</div>
// app/templates/components/serie-view.js
<div>
<h3> {{serie.title}} id: {{serie.id}}</h3>
Summary: {{serie.summary}}
</div>
And as http://localhost:4200/file works fin the http://localhost:4200/serie throw an error
I tried to tackle this by removing the unnecessary code and models so that I could narrow down the problem but ended up having two models that are very similar with almost copy-pasted functionality yet only one working.
I really have no idea what is this about anymore.
Your error gives you a hint
Encountered a resource object with type "series", but no model was found for model name "series" (resolved model name using 'my-app#serializer:-json-api:.modelNameFromPayloadKey("series"))
The problem is that ember knows how to switch between files and file but not between series and serie because the word series is irregular (both singular and plural) so serie is not its proper singular form.
Override modelNameFromPayloadKey method in your serializer to return the proper model name for the key 'series':
export default DS.JSONAPISerializer.extend({
modelNameFromPayloadKey(key) {
// if payload model name is 'series', use 'serie'
if (key === 'series') {
return 'serie';
}
// otherwise do the default thing
return this._super(...arguments);
}
});

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
}
});

Categories