I have a similar form, when I want to get submitted values in newItem controller, I get 'undefined' values. What's wrong?
<form role="form" {{ action 'add' target="newItem" on="submit"}}>
<h2>New category</h2>
<div class="form-group">
<label>Category title</label>
{{input value=title class="form-control" type="text" placeholder="Title"}}
</div>
<div class="form-group">
<label>Category description</label>
{{textarea value=description class="form-control" placeholder="Description"}}
</div>
<div class="form-group">
{{input type="submit" class="btn" }}
</div>
</form>
App.NewItemController = Ember.ObjectController.extend({
add: function(){
console.log(this.get('title')); // undefined
}
});
Update:
This form is on the ApplicationRoute:
App.ApplicationRoute = Ember.Route.extend({
setupController: function(controller, model) {
var newItem = this.controllerFor('NewItem');
controller.set('newItem', newItem);
}
});
You should try using Ember.TextField and Ember.TextArea:
<form role="form" {{ action 'add' target="newItem" on="submit"}}>
<h2>New category</h2>
<div class="form-group">
<label>Category title</label>
{{view Ember.TextField valueBinding="title"}}
</div>
<div class="form-group">
<label>Category description</label>
{{view Ember.TextArea valueBinding="description"}}
</div>
<div class="form-group">
{{input type="submit" class="btn" }}
</div>
</form>
The title and description values are now bound to the corresponding input fields.
Update:
I see your target is the newItem controller, so my guess is that this form is not bound to the NewItemController, thus the values are not bound to the NewItemController. A solution:
App.MyFormController = Ember.Controller.extend({
needs: ['newItem']
add: function(){
var newItemController = this.get('controllers.newItem');
newItemController.add(this.get('title'), this.get('description'));
}
});
App.NewItemController = Ember.ObjectController.extend({
add: function(title, description){
// add the new item here
}
});
Related
I have two models in Ember where one is a collection and the other is book. Collection model has a "hasMany" relationship with "book" and "book" "belongsTo" "collection". So what i want to do is have a form with both models in and store them at the same time.
Collection Model
// collection Model
export default DS.Model.extend({
name: DS.attr('string'),
city: DS.attr('string'),
books: DS.hasMany('book', { async: true })
});
The book model
//book Model
export default DS.Model.extend({
title: DS.attr('string'),
description: DS.attr('string'),
collection: DS.belongsTo('collection', {async: true})
});
The form
//Collection View
<div class="row">
<div class="col-sm-12">
<div class='panel panel-default'>
<div class='panel-body'>
<form>
<fieldset>
<legend>
Collection
</legend>
<div class="row">
<div class="col-sm-6">
<label for="name" class="col-sm-2">Name</label>
<div class="col-sm-10">
{{input id="name" type="text" class="form-control" value=collection.name}}
</div>
</div>
<div class="col-sm-6">
<label for="city" class="col-sm-2">city</label>
<div class="col-sm-10">
{{input id="city" type="text" class="form-control" value=collection.city}}
</div>
</div>
</div>
</fieldset>
<fieldset>
<legend>
books
</legend>
<div class="row">
<div class="col-sm-6">
<label for="title1" class="col-sm-2">title</label>
<div class="col-sm-10">
{{input id="title1" type="text" class="form-control" value=book.title1}}
</div>
</div>
<div class="col-sm-6">
<label for="description1" class="col-sm-2">description</label>
<div class="col-sm-10">
{{input id="description1" type="text" class="form-control" value=book.description1}}
</div>
</div>
</div>
<div class="row">
<div class="col-sm-6">
<label for="title2" class="col-sm-2">title</label>
<div class="col-sm-10">
{{input id="title2" type="text" class="form-control" value=book.title2}}
</div>
</div>
<div class="col-sm-6">
<label for="description2" class="col-sm-2">description</label>
<div class="col-sm-10">
{{input id="description2" type="text" class="form-control" value=book.description2}}
</div>
</div>
</div>
</fieldset>
<div class="row">
<div class="col-sm-12">
<button {{action 'addCollection'}} class="btn btn-primary">New Collection</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
The controller:
actions:{
addCollection: function(){
var name = this.get('collection.name');
var city = this.get('collection.city');
var title1 = this.get('book.title1');
var description1 = this.get('book.description1');
var title2 = this.get('book.title2');
var description2 = this.get('book.description2');
var newCollection = this.store.createRecord('collection', {
name: name,
city: city,
});
},
As you can see I'm trying to obtain 2 sets of books for this collection, but I'm having trouble on finding the correct procedure to store items to these models. I guess I may have to store the collection model first and then push the individual books to the collection. Is this correct? How would I go about it?
If the book is a record already you can simply push it onto the new collection. You don't don't need to assign anything to variables since your template is already bound to the record.
As an improvement I'd suggest creating the collection before the add as well. Either within your model, or on controller initiation.
So the action could be as simple as this.
actions:{
addCollection: function(){
// newCollection and Book need to be records
this.get("newCollection").pushObject(this.get('book'));
},
}
Note: the createRecord will not persist until you call .save() but you do not need to call .save() to create a relationship.
Forgive me for not noticing the multiple new books, here is a more pertinent example.
// template.hbs
<div class="row">
<div class="col-sm-12">
<div class='panel panel-default'>
<div class='panel-body'>
<form>
<fieldset>
<legend>
Collection
</legend>
<div class="row">
<div class="col-sm-6">
<label for="name" class="col-sm-2">Name</label>
<div class="col-sm-10">
{{input id="name" type="text" class="form-control" value=model.newCollection.name}}
</div>
</div>
<div class="col-sm-6">
<label for="city" class="col-sm-2">city</label>
<div class="col-sm-10">
{{input id="city" type="text" class="form-control" value=model.newCollection.city}}
</div>
</div>
</div>
</fieldset>
<fieldset>
<legend>
books
</legend>
<div class="row">
<div class="col-sm-6">
<label for="title1" class="col-sm-2">title</label>
<div class="col-sm-10">
{{input id="title1" type="text" class="form-control" value=model.book1.title}}
</div>
</div>
<div class="col-sm-6">
<label for="description1" class="col-sm-2">description</label>
<div class="col-sm-10">
{{input id="description1" type="text" class="form-control" value=model.book1.description}}
</div>
</div>
</div>
<div class="row">
<div class="col-sm-6">
<label for="title2" class="col-sm-2">title</label>
<div class="col-sm-10">
{{input id="title2" type="text" class="form-control" value=model.book2.title}}
</div>
</div>
<div class="col-sm-6">
<label for="description2" class="col-sm-2">description</label>
<div class="col-sm-10">
{{input id="description2" type="text" class="form-control" value=model.book2.description}}
</div>
</div>
</div>
</fieldset>
<div class="row">
<div class="col-sm-12">
<button {{action 'addCollection' model}} class="btn btn-primary">New Collection</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
// route.js
model () {
return Ember.RSVP.hash({
newCollection: this.get('store').createRecord('collection'),
book1: this.get('store').createRecord('book'),
book2: this.get('store').createRecord('book')
})
}
// controller.js
actions:{
addCollection(model) {
model.newCollection.pushObject(model.book1);
model.newCollection.pushObject(model.book2);
},
}
Notice I've used the model to create the records before hand and it's being passed into the action. You still may need to save for these changes to persist.
I tried other answers here on SO but none of them helped.
app/routes/card/new.js
actions: {
save(title, description) {
const newCard = this.get('store').createRecord('card', { title, description } );
newCard.save().then((card) => {
this.transitionTo('card.card', card);
});
}
}
For the view, I've:
app/templates/card/new.hbs
<form>
<fieldset class="form-group">
<label for="card-title">Card Title</label>
{{input type="text" value=title class="form-control" id="card-title" placeholder="Enter the title of the card"}}
<small class="text-muted">Give your card a nice title</small>
</fieldset>
<fieldset class="form-group">
<label for="card-description">Card Description</label>
{{textarea value=description class="form-control" id="card-description" rows="3"}}
<small class="text-muted">Describe your card</small>
</fieldset>
<div class="btn-group" role="group" aria-label="Save or Cancel your card">
<button {{action 'save' title description}} class="btn btn-secondary">Save</button>
<button {{action 'cancel'}} class="btn btn-danger">Cancel</button>
</div>
</form>
When I create a card, it works fine but when I again try creating a new car, the form retains the old values which disappears on refresh.
app/routes/card/new.js
model(){
return this.get('store').createRecord('card');
}
app/controllers/card/new.js
actions: {
save(){
this.get('model').save().then((card) => {
this.transitionTo('card.card', card);
});
}
}
app/templates/card/new.hbs
<form>
<fieldset class="form-group">
<label for="card-title">Card Title</label>
{{input type="text" value=model.title class="form-control" id="card-title" placeholder="Enter the title of the card"}}
<small class="text-muted">Give your card a nice title</small>
</fieldset>
<fieldset class="form-group">
<label for="card-description">Card Description</label>
{{textarea value=model.description class="form-control" id="card-description" rows="3"}}
<small class="text-muted">Describe your card</small>
</fieldset>
<div class="btn-group" role="group" aria-label="Save or Cancel your card">
<button {{action 'save'}} class="btn btn-secondary">Save</button>
<button {{action 'cancel'}} class="btn btn-danger">Cancel</button>
</div>
</form>
I'm new to ember and trying to build a very simple app as a learning exercise in 2.4. I have a list of tasks that appear on the index page. And I've attached actions to each one to delete. And have one form row on the bottom of the page with an action to saveTask.
I have one index controller.
No defined index routes.
One model for tasks at app/models/task.js
My function to saveTask is working. But I can't get the deleteTask to work. I know I'm not passing the object I want to delete correctly. The error returned is that Uncaught TypeError: undefined is not a function index.js:26
deleteTask.
Can someone explain the correct syntax to me?
app/templates/index.hbs
{{#each model as |task| }}
<div class="form-horizontal form-group row">
<div class="col-xs-4 col-md-3">
{{input type="text" value=task.taskname class="form-control"}}
</div>
<div class="col-xs-3 col-md-2">
{{input type="text" value=task.startdate class="form-control"}}
</div>
<div class="col-xs-3 col-md-2">
{{input type="text" value=task.enddate class="form-control"}}
</div>
<div class="col-xs-3 col-md-2">
{{input type="text" value=task.duration class="form-control"}}
</div>
<div class="col-xs-3 col-md-2">
{{input type="text" value=task.banding class="form-control"}}
</div>
<div class="col-xs-2 col-md-1">
<button type="button" class="btn btn-default btn-sm" aria-label="Remove task" {{action 'deleteTask' task}}>
<span class="glyphicon glyphicon-remove" aria-hidden="true"></span>
</button>
</div>
</div>
{{/each}}
and the controller
app/controllers/index.js
import Ember from 'ember';
export default Ember.Controller.extend({
actions: {
deleteTask(task) {
this.destroyRecord();
this.transitionTo('index');
}
}
});
You call destroyRecord in deleteTask on this not on the task, which is actually the record. I think that's all.
You should be able to see in developer tools the line in code which throws. I bet it's this.destroyRecord();.
Hi I'm trying to create a select list as part of a login form. The form submits and passes the two input text values but doesn't see the select list.
<form id="form-login" {{action 'authenticate' on='submit'}}>
<fieldset>
{{input id='identification' value=identification placeholder='Username'}}
{{input id='password' value=password placeholder='Password' type='password'}}
<select id="language" name="language">
<option value="ENG">English</option>
<option value="">Not English</option>
</select>
</fieldset>
{{#if errorMessage}}
<div>
<strong>Login failed:</strong> {{errorMessage}}
</div>
{{/if}}
<button type="submit" class="btn btn-default">Login</button>
</form>
I tried these steps but it says they're deprecated and don't work? http://emberjs.com/api/classes/Ember.Select.html
{{view "select" content=languages value=selectedLanguage}}
That's the only page on their documentation I could find?
Thanks!
The selected value needs to be set on the context. Right now the value isn't being set at all.
controller
import Ember from 'ember';
export default Ember.Controller.extend({
language: 'English',
languages: ['English', 'Non English'],
actions: {
authenticate() {
// Set values from form and submit to server...
}
}
});
template
<form id="form-login" {{action 'authenticate' on='submit'}}>
<fieldset>
{{input id='identification' value=identification placeholder='Username'}}
{{input id='password' value=password placeholder='Password' type='password'}}
<select onchange={{action (mut language) value="target.value"}} id="language" name="language">
{{#each languages as |languageChoice|}}
<option value={{languageChoice}} selected={{eq language languageChoice}}>{{languageChoice}}</option>
{{/each}}
</select>
</fieldset>
{{#if errorMessage}}
<div>
<strong>Login failed:</strong> {{errorMessage}}
</div>
{{/if}}
<button type="submit" class="btn btn-default">Login</button>
</form>
Here's a post with a good explanation of everything that's going on.
I successfully use this code from a route to popup a boostrap model:
this.render("login-modal", {
into: 'application',
outlet: 'modal'
});
I have login template and the actions is handle through a controller. What I want to do is to pop the modal if the login is failed through the controller.
LoginController:
App.LoginController = Ember.Controller.extend({
needs: ['application'],
actions: {
submit: function() {
var username = this.get('username');
var password = this.get('password');
var self = this;
var postData = JSON.stringify({
"username": username,
"password": password
});
self.set('errorMessage', null);
$.ajax({
type: 'POST',
contentType: 'application/json',
url: 'api/auth',
dataType: "json",
data: postData,
success: function(response){
self.set('errorMessage', response.message);
if (response.success) {
self.set('token', response.token);
self.set('loginstatus', 'success');
var appController = self.get('controllers.application');
appController.set('token', response.token);
self.transitionToRoute('/');
}
if (response.message) {
//console.log('login failed');
self.get('login').render("login-modal-failed", {
into: 'application',
outlet: 'modal'
});
}
},
error: function() {
alert("An error occurred while processing JSON file.");
}
});
}
}
this is the failed code:
if (response.message) {
//console.log('login failed');
self.get('login').render("login-modal-failed", {
into: 'application',
outlet: 'modal'
});
}
the error: Uncaught TypeError: Cannot read property 'render' of undefined
The Login template
<script type="text/x-handlebars" data-template-name="login">
<h1>LOGIN</h1>
<p>Please enter login info</p>
<form class="form-inline" role="form" {{action 'submit' on="submit"}}>
<div class="form-group">
{{input type="text" class="form-control" placeholder="Username" value=username}}
</div>
<div class="form-group">
{{input type="password" class="form-control" placeholder="Password" value=password}}
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
{{#if errorMessage}}
<br />
<div class="alert alert-warning alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
<strong>Warning!</strong> Wrong username and/or password.
</div>
{{/if}}
</script>
The bootstrap modal component
<script type="text/x-handlebars" data-template-name="components/my-modal">
<div class="modal fade">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">{{title}}</h4>
</div>
<div class="modal-body">
{{yield}}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" {{action 'ok'}}>OK</button>
</div>
</div>
</div>
</div>
</script>
The bootstrap modal template based on the component above
<script type="text/x-handlebars" data-template-name="login-modal-failed">
{{#my-modal title='Login Failed' ok='failed'}}
Login failed - wrong username/password!
{{/my-modal}}
</script>