/ exams / template.hbs
<form>
<select name="selectvalue" id="selectvalue">
<option value="one"> One </option>
<option value="two"> Two </option>
<option value="three"> Three </option>
</select>
<button type="submit" {{action "printans"}}> Submit </button>
</form>
/ exams / controller.hbs
import Controller from '#ember/controller';
export default Controller.extend({
actions: {
printans: function(){
let val = this.get('selectvalue');
console.log(val);
}
}
});
All I need is I want to replace the html code in the template.hbs with handlebars, and when the form is submitted, I need to pass the value to the controller.
Do you mean something like:
<form>
{{#power-select
selected=selectvalue
options=cities
onchange=(action "printans")
as |name|
}}
{{name}}
{{/power-select}}
</form>
I'm totally guessing here.
Additional Details would be helpful:
- what are you trying to do (specifically)
- where do you get your list of items?
There is this addon, which covers a lot more common behavior: https://github.com/cibernox/ember-power-select
Related
I have a JSON object consisiting of an array of json objects.
I want to display the provider group List for every application as a dataList in my JSON object .
The JSON object is :
{"Application1":[{"pg_id":"test00020","pg_name":"test20","sealID":"Application1"},{"pg_id":"test00030","pg_name":"test30","sealID":"Application1"}],"Application2":[{"pg_id":"test00040","pg_name":"test40","sealID":"Application2"},{"pg_id":"test00050","pg_name":"test50","sealID":"Application2"}]}
I have named this JSON object as AppPgMap and in my hbs file I am trying to access it as follows:
**<input class="typeahead" type="text" id={{concat "pg_id_input" index index_new}} list="pg_data" onchange= {{action "getProviderGroups" }} placeholder="search here">
<datalist id="pg_data">
<select class="form-control " id= "new_pg_id" oninput={{action (mut el.value) value="target.value" }} required=true>
{{#each AppPgMap as |application| }}
{{#each application as |providerGroup|}}
<option value={{ providerGroup.pg_id }}> {{providerGroup.pg_name}}</option>
{{/each}}
{{/each}}
</select>
</datalist>**
This doesn't work for me and instead of getting the data list i get an empty input field .
Is there a solution to this? Or do I have to restructure my data and try displaying it another way?
For iterating over an object you can use each-in helper
{{#each-in PgMap as |appName appDetails| }}
{{#each appDetails as |providerGroup|}}
<option value={{ providerGroup.pg_id }}> {{providerGroup.pg_name}}</option>
{{/each}}
{{/each-in}}
I am an extreme newbie, for which I apologize, but I'm not finding this...
In templates/editor/journal.hbs, this works:
<h2>Journal template</h2>
<select>
<option value="" disabled="disabled" selected="selected">Periodicals:</option>
{{#each model as |journal|}}
<option value="{{journal.id}}"> {{journal.name}}</option> {{journal}}
{{/each}}
</select>
{{outlet}}
But the same code, in my component (journal-list), does not...
with journal.hbs changed to
<h2>Journal template</h2>
{{journal-list title="Crazy Test" model=journal}}
{{outlet}}
And that code in journal-list.hbs,
{{yield}}
<h1>{{title}}</h1>
<select>
<option value="" disabled="disabled" selected="selected">Periodicals:
</option>
{{#each model as |journal|}}
<option value="{{journal.id}}"> {{journal.name}}</option>
{{/each}}
</select>
all stubs generated by ember generate, I do get the title but the listview is unpopulated.
What magic am I missing? Do I need to configure a route to the component, for example?
Thanks
Uggah. I did spend over an hour on that before posting!
It's simple. Instead of journal.hbs having model=journal, it needed model=model.
I have the following in my template:
<select>
{{#each sortedManufacturers key="id" as |manufacturer|}}
<optgroup label="{{manufacturer.name}}">
{{#each manufacturer.cars key="id" as |car|}}
<option {{action "carSelected" car}} value="{{car.model}}">{{car.model}}</option>
{{/each}}
</optgroup>
{{/each}}
</select>
In the controller, I have:
actions: {
carSelected(car) {
console.log(car);
}
}
When the option is selected from the select. It doesn't seem to trigger the carSelected action.
Any ideas why?
In Ember > 1.13 you can do the following:
<select onchange={{action "carSelected" value="target.value"}}>
<!-- ... -->
</select>
With component JS:
export default Component.extend({
actions: {
carSelected(car) {
// ..
}
}
});
Or you can use the unquoted “closure action” form:
<select onchange={{action carSelected value="target.value"}}>
<!-- ... -->
</select>
With component JS:
export default Component.extend({
carSelected(car) {
// ..
}
});
See the improved actions RFC for more on all this.
I don't exactly know why click event is not binded to option this way. I beleive it's better to use change event on select instead.
<select {{action 'carSelected' on='change'}}> ... </select>
Here is implementation details: http://emberjs.com/deprecations/v1.x/#toc_ember-select
In Ember's input helper, how can I show/hide attributes based on a condition? For example, let's say I want to show required="required" if isEditable is true and disabled="disabled" otherwise. Currently I have something like this:
{{#if isEditable}}
{{input value=model.name required="required"}}
{{else}}
{{input value=model.name disabled="disabled"}}
{{/if}}
...but it would be nice if I bind the attributes somehow instead.
{{ input type='text' required=required disabled=disabled }} works just fine
Working example here
There are a whole bunch of attributes that you can bind directly and required and disabled are among the pack. See here
Note #blackmind is correct that if you were to do this from scratch, you would need to do some work. Fortunately though, TextSupport already does the work for you... :) See here
From the EmberJS site
By default, view helpers do not accept data attributes. For example
{{#link-to "photos" data-toggle="dropdown"}}Photos{{/link-to}}
{{input type="text" data-toggle="tooltip" data-placement="bottom" title="Name"}}
renders the following HTML:
<a id="ember239" class="ember-view" href="#/photos">Photos</a>
<input id="ember257" class="ember-view ember-text-field" type="text" title="Name">
There are two ways to enable support for data attributes. One way would be to add an attribute binding on the view, e.g. Ember.LinkView or Ember.TextField for the specific attribute:
Ember.LinkView.reopen({
attributeBindings: ['data-toggle']
});
Ember.TextField.reopen({
attributeBindings: ['data-toggle', 'data-placement']
});
Now the same handlebars code above renders the following HTML:
<a id="ember240" class="ember-view" href="#/photos" data-toggle="dropdown">Photos</a>
<input id="ember259" class="ember-view ember-text-field"
type="text" data-toggle="tooltip" data-placement="bottom" title="Name">
Or you can reopen the view
Ember.View.reopen({
init: function() {
this._super();
var self = this;
// bind attributes beginning with 'data-'
Em.keys(this).forEach(function(key) {
if (key.substr(0, 5) === 'data-') {
self.get('attributeBindings').pushObject(key);
}
});
}
});
I typically do the following
<input type="checkbox" {{bind-attr disabled=isAdministrator}}>
I've only just started using Ember and am struggling with a couple of concepts. I used Knockout for a previous application which was great, and I can already see how Ember will help me be more structured and write less code. Although I could go back to Knockout and get this up and running pretty quickly, I really want to persevere with Ember.
The bit I'm struggling with is the right way and place to load related records. My app has a list of systems, and a list of suppliers related to each system. Each system may have one or more suppliers, and vice-versa.
So far I have a route called Systems with a corresponding controller and template. The model hook on the route gets the list of systems from an API (I'm using Ember Data). The systems are displayed as a list via the template, and when the user selects one (via a radio button) I need to load and display the related suppliers. That's the bit I'm not sure about.
I'm not changing the URL here, just displaying an additional list of suppliers underneath the list of systems so adding a new route doesn't sound quite right. Conceptually what would be the best way to do this?
Should I use an action in the controller to load and display the data? That doesn't sound quite right either as the model hooks are all in the routes.
Should I just load the data all up front and filter it (and toggle display) using the controller?
Is there a right, or better, way?
Here's the current code.
System Model
import DS from 'ember-data';
export default DS.Model.extend({
name: DS.attr('string'),
suppliers: DS.hasMany('supplier')
});
Supplier Model
import DS from 'ember-data';
export default DS.Model.extend({
name: DS.attr('string'),
systems: DS.hasMany('system')
});
Systems Route
import Ember from 'ember';
export default Ember.Route.extend({
model: function() {
return this.store.find('system');
}
});
Systems Controller
import Ember from 'ember';
export default Ember.ObjectController.extend({
systemSelected: false,
actions: {
selectSystem: function(id) {
this.set('systemSelected', true);
console.log(id);
},
selectSupplier: function(supplier) {
console.log(supplier);
}
}
});
Systems Template
<h1>systems</h1>
<form id="systems">
<fieldset>
<div class="form-group">
<label for="system" class="control-label">Select the system</label>
{{#each}}
<div class="radio">
<label>
<input type="radio" name="system" value="{{id}}" {{action 'selectSystem' id}}>
<span>{{name}}</span>
</label>
</div>
{{/each}}
</div>
{{#if systemSelected}}
<div class="form-group">
<label for="supplier" class="control-label">Select the supplier</label>
{{#each suppliers}}
<div class="radio">
<label>
<input type="radio" name="supplier" value="{{id}}" {{action 'selectSupplier' supplier}}>
<span>{{name}}</span>
</label>
</div>
{{/each}}
</div>
{{/if}}
</fieldset>
</form>
The way to handle this is pretty simple. You just load both related models in your route. You do that using RSVP.
First of all, we'll need a Suppliers Controller, but just a really basic one to store all the Suppliers:
App.SuppliersController = Ember.ArrayController.extend();
In your Systems Route, fetch the models like this and set them to the correct model properties:
import Ember from 'ember';
export default Ember.Route.extend({
model: function() {
return Ember.RSVP.hash({
systems: store.find('system'),
suppliers: store.find('suppliers')
});
},
setupController(controller,models) {
this.controllerFor('systems').set('model',models.systems);
this.controllerFor('suppliers').set('model',models.suppliers);
}
});
Then in your Systems Controller, add the Suppliers Controller to the needs:
import Ember from 'ember';
export default Ember.ObjectController.extend({
needs:['systems'],
systemSelected: false,
actions: {
selectSystem: function(id) {
this.set('systemSelected', true);
console.log(id);
},
selectSupplier: function(supplier) {
console.log(supplier);
}
}
});
You might want to use an ArrayController instead of an ObjectController for Systems Controller since it stores more than one object.
Then in your Systems Template, you can access the Systems Controller as a property of your main controller, like this:
<h1>systems</h1>
<form id="systems">
<fieldset>
<div class="form-group">
<label for="system" class="control-label">Select the system</label>
{{#each system in controllers.systems}}
<div class="radio">
<label>
<input type="radio" name="system" value="{{id}}" {{action 'selectSystem' id}}>
<span>{{name}}</span>
</label>
</div>
{{/each}}
</div>
{{#if systemSelected}}
<div class="form-group">
<label for="supplier" class="control-label">Select the supplier</label>
{{#each suppliers}}
<div class="radio">
<label>
<input type="radio" name="supplier" value="{{id}}" {{action 'selectSupplier' supplier}}>
<span>{{name}}</span>
</label>
</div>
{{/each}}
</div>
{{/if}}
</fieldset>
</form>
There ya go. Hope that helps. There are other ways to do this, but this is the most Emberific way to do it that I know.