Create reusable Ember.Select control with parameters - ember.js

I would like to create a specialized select control view, which should simply add some functionality. For simplicity I would just like to be able to add a title.
The Control/View:
window.App.ControlsSelectView = Ember.View.extend({
templateName: 'controls/SelectView',
title:"Hello Control",
contentBinding: null
});
The matching html:
<div class="sub_heading">
<h2>{{title}}</h2>
</div>
<div class="inner_12 input_wrapper custom_select">
{{view Ember.Select
multiple="true"
contentBinding= "contentBinding" // how to pass parameters through?
selectionBinding="content.tempSelectedFunctions"
optionLabelPath="content.displayname"
optionValuePath="content.id"
}}
</div>
Usage should be something like this:
{{ view App.ControlsSelectView
contentBinding="content.data.responsibilities"
selectionBinding="content.tempSelectedFunctions"
title="content.responsibilitTitle"
}}
Problem is, that it doesn't work like that. Is the above possible? Or is there a better pattern to create simple reuasble controls?

This post helped me to get on the right track:
get content in view from ContentBinding
Inside the html of the control view I need to reference the view parameters with view.propertyname
Working solution:
HTML:
<div class="sub_heading">
<h2>{{view.title}}</h2>
</div>
{{#if view.content}}
<div class="inner_12 input_wrapper custom_select">
{{view Ember.Select
multiple="view.multiple"
contentBinding= "view.content"
selectionBinding="view.selection"
optionLabelPathBinding="view.optionLabelPath"
optionValuePathBinding="view.optionValuePath"
}}
</div>
{{/if}}
ControlView
window.App.ControlsSelectView = Ember.View.extend({
templateName: 'controls/SelectView'
});
Usage:
{{view App.ControlsSelectView
title = "Function"
multiple="true"
contentBinding="content.data.functions"
selectionBinding="content.tempSelectedFunctions"
optionLabelPath="content.displayname"
optionValuePath="content.id"
}}

Related

how to fire change event on select emberjs

The behavior that i want is when changing the select is to save it's model
I though about using observable, but i have another problem
my view looks something like this
{{#each item in model.Items}}
<div class="select">
{{view Ember.Select
content=typesLookup
selection=type
prompt="Select Type"
}}
</div>
{{/each}}
so if i went with the observables solution, what i want is to also know the specific item that has changed to update it
add the observer and selection on an itemController.
App.FooController = Em.ObjectController.extend({
type:undefined,
watchType: function(){
console.log('this model changed', this.get('model'));
}.observes('type')
});
{{#each item in model.Items itemController='foo'}}
<div class="select">
{{view Ember.Select
content=typesLookup
selection=item.type
prompt="Select Type"
}}
</div>
{{/each}}

Ember view with dynamic class names

Considering the following:
Parent template:
{{view App.SomeView id="42" panelClass="default"}}
View template:
<div class="col-md-3 col-sm-6">
<div class="panel panel-{{panelClass}}">
<div class="panel-heading">
<h3 class="panel-title">
{{name}}
</h3>
</div>
<div class="panel-body">
{{description}}
</div>
</div>
</div>
View JS:
App.SomeView = Ember.View.extend({
templateName: 'views/some-view'
});
How can I achieve output HTML where the panel class gets set properly? At the moment it doesn't work because it wants to bind, so it inserts the ember metamorph script tags, instead of just plain text for the panel class.
Also, the template is wrapped in an extra div. How would I modify it so that the ember-view wrapping div is actually the first div in the template (the one with col-md-3 col-sm-6)?
The bind-attr helper exists for that reason. Here's the guide entry.
<div {{bind-attr class=":panel panelClass"}}></div>
Also, not sure if you can use a prefix on panelClass in the template. If might be easier just to use a computed property to add the panel- beforehand.
I'm sorry, I didn't see your second question about the extra div. The guide explains here how to extend the element.
App.SomeView = Ember.View.extend({
classNames: ['col-md-3', 'col-sm-6']
});

How to set itemController for instance variable in ember.js indexController?

I have a Ember.js page that displays a table of items and shows details of one of the items when it is selected. The controller looks like this:
CV.IndexController = Ember.ArrayController.extend({
itemController: "CurrVitae",
selectedCurrVitae: false,
actions: {
selectCurrVitae: function(currVitae) {
this.set('selectedCurrVitae', currVitae)
}
}
});
And the index controller is used in a template like this:
<div class="container">
<div class="curr-vitae-list">
{{#each curr_vitae in controller}}
<div class="curr-vitae-item row">
<div class="col-sm-2" {{action selectCurrVitae curr_vitae}}>
{{curr_vitae.name}}
</div>
<div class="col-sm-2">
<!-- NOTE: This method is defined on the item
controller (not the model) so the itemController is
available at this point. -->
{{curr_vitae.createdAtDisplay}}
</div>
<div class="col-sm-7">
<div class="embedded-cell">
{{curr_vitae.summary}}
</div>
<div class="embedded-cell">
{{curr_vitae.objective}}
</div>
</div>
</div>
{{/each}}
</div>
<div class="curr-vitae-view">
<h2>Details</h2>
<!-- EDIT: I have tried setting this
as {{#if selectedCurrVitae itemController="currVitae" }}
to match the way the #each handles item controllers but that did
not seem to work -->
{{#if selectedCurrVitae }}
<!-- NOTE: Down here, however, the item controller is not available
so I can't use methods defined on the item controller for the
currently selected instance. -->
{{ partial "cv_index_details" }}
{{/if}}
</div>
</div>
Question: The problem I'm running in to is that the itemController I've set in the index controller is not available when rendering the selectedCurrVitae in the cv_index_details.
More details:
Specifically, in the partial I want to reuse a editor component (taken from Noel Rappin's Ember.js book). So if the cv_index_details partial looks like this:
<h3 class="selected_cv">{{selectedCurrVitae.name}}</h3>
<div class="row selected_cv_summary">
<h4>Summary</h4>
{{block-editor emberObject=selectedCurrVitae propName="summary" action="itemChanged"}}
</div>
<div class="row selected_cv_experiences">
<h4>Experiences</h4>
{{#each experience in selectedCurrVitae.experiences itemController="experience"}}
{{ partial "experience_detail" }}
{{/each}}
</div>
So in this template, the itemChanged action is not found for the selectedCurrVitae instance. However, I use the same block-editor component for the experience instance and that works correctly; the itemChanged action defined on the ExperienceController is found.
selectedCurrVitae is outside of the itemController, the itemController is only applied inside the each (on each item, hence the name).
Probably the easiest way to accomplish this will be to reuse the item controller and use render.
Template
{{#if selectedCurrVitae }}
{{ render "cv_index_details" }}
{{/if}}
Controller
CV.CvIndexDetailsController = CV.CurrVitaeController.extend();
Or
Template
{{#if selectedCurrVitae }}
{{ render "currVitae" }}
{{/if}}
View
CV.CurrVitaeView = Ember.View.extend({
templateName: 'cv_index_details'
});

Nesting existing textfield view in a new view

I have been getting a bit stuck in finding a way to reuse an ember textfield so any help would be appreciated.
What I have is (simplified here) a selection of rows like:
<div class="detailItem">Email: {{view Ember.TextField valueBinding="email"}} </div>
<div class="detailItem">Name: {{view Ember.TextField valueBinding="name"}} </div>
and instead of always wrapping in a div I'd like to make use of a new view. e.g.:
<script type="text/x-handlebars" data-template-name="detailItem">
<div class="detailItem">{{Item name}}: {{view Ember.TextField valueBinding="itemValue"}} </div>
</script>
App.DetailItemView = Em.View.extend({
templateName: 'detailItem',
name: "",
......
});
The thing I am not sure is how I get the textfield's valueBinding to link up to my controller (well actually it's content). I can obviously add another property to DetailItemView and instantiate it with that property having the values 'email' and 'name'. How though would I then pass these into the contained Ember.TextField?
Thanks for any assistance
You can do the following:
App.DetailItemView = Ember.View.extend({
templateName: 'detail_item',
classNames: ['detailItem'],
label: null,
value: ''
});
and the template:
<script type="text/template" id="detail_item">
{{view.label}}:
{{view Ember.TextField valueBinding="view.value"}}
</script>
And then use it like this:
{{view App.DetailItemView label="Email" valueBinding="email"}}
{{view App.DetailItemView label="Name" valueBinding="name"}}

Ember.js View not properly passing context to router even

I am having a bit of trouble with ember.js.
I have the following code which properly calls the event in the router to create the notebook. However, it will not pass the notebook context, it it undefined. I have been searching for hours to try and find a solution for this.
I found this and this, which are helpful but I'm not completely sure I'm on the right track. Am I missing something?
Route
App.NotebooksNewRoute = Ember.Route.extend
model: ->
App.Notebook.createRecord()
events:
create: (notebook) ->
#persist notebook
Form
{{#with content}}
<form {{action create content on="submit" }} >
<div>
{{view Ember.TextField placeholder="Enter a title" valueBinding="title" }}
</div>
<div>
{{view Ember.TextArea placeholder="Notes" valueBinding="description" }}
</div>
<button type="submit">Create</button>
</form>
{{/with}}
Am I missing something?
Change {{action create content on="submit" }} to {{action create this on="submit" }}
Why?
When you use the handlebars helper {{#with}}, the enclosed block will be rendered in the context of the specified variable. So after {{#with content}}, this is whatever content was and you can access properties like title and description directly instead of content.title and content.description