通过native select元素更新belongsTo关系 [英] Update belongsTo relationship via native select element

查看:224
本文介绍了通过native select元素更新belongsTo关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在尝试整合 Brenna O'Brien 的Ember Conf 2016演讲细节 < select> ing Good Ember Patterns 进入一个项目,它正在为简单的属性工作(在下面的例子中 names 是一个字符串数组, model.name 是一个 attr(string)):

 < select onchange = {{action(mut model.name)value =target.value}}> 
{{#each names as | name |}}
< option value = {{name}} selected = {{eq name model.name}}> {{name}}< /选项>
{{/ each}}
< / select>

但是,当应用于 belongsTo 关系和一系列模型:



控制器

从$ ember导入Ember; 

导出默认Ember.Controller.extend({
titles:null,
init(){
this.set(titles,this.store.peekAll (title));
}
});

模板

 < select onchange = {{action(mut model.title)value =target.value}}> 
{{#each titles as | title |}}
< option value = {{title}} selected = {{eq title.id model.title.id}}>
{{title.description}}
< / option>
{{/ each}}
< / select>

此失败;关系值被修改,但没有设置为有效的标题。从一些分析来看,似乎标题模型被HTMLBar处理或者当它被设置为 option.value ,当这个关系设置时,这不是(不能?)被转换。



我目前已经解决了这个问题( Ember-Twiddle )通过向控制器添加一个操作:

  actions:{
title(id){
this.set('model.title',this.store.peekRecord(title,id));
}
}

并修改模板来调用:

 < select onchange = {{actiontitlevalue =target.value}}> 
{{#each titles as | title |}}
< option value = {{title.id}} selected = {{eq title.id model.title.id}}>
{{title.description}}
< / option>
{{/ each}}
< / select>

然而,我需要为这种方式更新的每个关系创建一个函数。 / p>

有没有办法从模板直接设置一个 belongsTo 关系,而不调用中间函数或使用add-项? (如果不是那么一个DRY方法来解决这个问题?)

解决方案

不幸的是,直到我们有可路由的组件,没有这样做不会从组件发送操作。幸运的是,我们有 ember-route-action-helper 可以帮助我们,这样做可以作为可路由组件的垫片。 ( https://github.com/DockYard/ember-route-action-helper) - 我知道你说你想避免加载项,但这是唯一的不涉及在组件中定义动作的解决方案(据我所知)。此外,这是一个非常有用的附加组件。我正在使用它用于这种用例和其他。奖金:当可路由组件具有土地时,您将不会真的需要进行任何重构。无论如何,这是我如何解决这个问题:



您可以在路线上指定操作,并使用Mixin for DRY。一个Mixin,你也可以只是扩展Route并继承,或者你可以重新打开Route,我反对重新打开Route,因为你不太可能需要在每一条路线上采取这种行动,避免膨胀。)



此Mixin假定您引用的model属性和belongsTo模型将始终具有相同的名称,因此只能使用一个变量: property 。如果不是这种情况,您需要将另一个参数添加(并传递)到 setBelongsTo()并指定哪个参数用于集合() peekRecord()



测试并在 ember-cli:2.13.2



选项1:本地选择方法



注意: ember-route-action-helper 需要加载项

  // mixins / my-mixin.js 

从ember导入Ember;

导出默认值Ember.Mixin.create({
actions:{
setBelongsTo(model,property,value){
this.get('controller')。 get(model).set(property,this.store.peekRecord(property,value));
}
}
});





  // routes / my-route.js 

从ember导入Ember;
从'myApp / mixins / set-belongs-to'导入SetBelongsToMixin;

导出默认值Ember.Route.extend(SetBelongsToMixin,{
model(){
return this.get('store')find(...);
}
});





  // templates / my-route.hbs 

< select onchange = {{action(route-action'setBelongsTo''model''title')value =target.value} }>
{{#each titles as | title |}}
< option value = {{title.id}} selected = {{eq title.id model.title.id}}>
{{title.description}}
< / option>
{{/ each}}
< / select>

选项2: ember-power-select 方法



注意: ember-route-action-helper 如果使用 ember-power-select $ c $( https://github.com/cibernox/ember-power-select

  // mixins / my-mixin.js 

从ember导入Ember;

导出默认值Ember.Mixin.create({
actions:{
setBelongsTo(model,property,value){
this.get('controller')。 get(model).set(property,value);
}
}
});





  // routes / my-route.js 

从ember导入Ember;
从'myApp / mixins / set-belongs-to'导入SetBelongsToMixin;

导出默认值Ember.Route.extend(SetBelongsToMixin,{
model(){
return this.get('store')find(...);
}
});





  // templates / my-route.hbs 

{{#power-select
options = titles
selected = model.title
onchange =(action (route-action'setBelongsTo''model''title'))
as | title |
}}
{{title.description}}
{{/ power-select}}

编辑1: OP使用 ember-truth-helpers 加载项设置所选择的选项。 (或OP创建自己的帮助者 eq 。)这里的第一个解决方案也使用这个加载项。


I have been trying to incorporate details of Brenna O'Brien's Ember Conf 2016 talk <select>ing Good Ember Patterns into a project and it is working for simple attributes (in the example below names is an array of strings and model.name is an attr( "string" )):

<select onchange={{action (mut model.name) value="target.value"}}>
  {{#each names as |name|}}
    <option value={{name}} selected={{eq name model.name}}>{{name}}</option>
  {{/each}}
</select>

However, when this is applied to a belongsTo relationship and an array of models:

Controller:

import Ember from 'ember';

export default Ember.Controller.extend({
  titles: null,
  init(){
    this.set( "titles", this.store.peekAll( "title" ) );
  }
});

Template:

<select onchange={{action (mut model.title) value="target.value"}}>
  {{#each titles as |title|}}
    <option value={{title}} selected={{eq title.id model.title.id}}>
      {{title.description}}
    </option>
  {{/each}}
</select>

This fails; the relationship value is modified but it is not set to a valid title. From some analysis, it appears that the title model is stringified either when it is being handled by HTMLBars or when it is set as the option.value and this is not (cannot?) being converted back when the relationship is set.

I have currently solved it (Ember-Twiddle) by adding an action to the controller:

actions: {
  title( id ){
    this.set( 'model.title', this.store.peekRecord( "title", id ) );
  }
}

and modifying the template to call this:

<select onchange={{action "title" value="target.value"}}>
  {{#each titles as |title|}}
    <option value={{title.id}} selected={{eq title.id model.title.id}}>
      {{title.description}}
    </option>
  {{/each}}
</select>

However, I then need to create a function for each relationship I want to update in this way.

Is there a way to directly set a belongsTo relationship from the template without calling an intermediate function or resorting to add-ons? (If not then is there a DRY method of solving this?)

解决方案

Unfortunately, until we have routable components, there is no way to do this without sending an action from the component. Fortunately, we have ember-route-action-helper to help us, and this acts as sort of a shim for routable components. (https://github.com/DockYard/ember-route-action-helper) - I know you said you wanted to avoid add-ons but this is the only "solution that does not involve defining actions in the component" available at this point in time (as far as I know). Furthermore, it's a very helpful add-on in general. I'm using it for this use case and others. Bonus: when the routable components feature lands, you won't really have to do any refactoring. Anyhow, this is how I solved this problem:

You can specify the action on the route, and use a Mixin for DRY. (Instead of a Mixin, you could also just extend Route and inherit from that, or you could reopen Route. I would be opposed to reopening Route, because you are very unlikely to need this action on every single route. Avoid bloat.)

This Mixin presumes that your model property and the belongsTo model that it references will always have the same name, so only uses one variable: property. If this is not the case, you'll need to add (and pass) another parameter to setBelongsTo() and specify which parameter is used for set() and peekRecord().

Tested and works on ember-cli: 2.13.2

Option 1: Native Select Method

note: ember-route-action-helper add-on is required

// mixins/my-mixin.js

import Ember from 'ember';

export default Ember.Mixin.create({
  actions: {
    setBelongsTo(model, property, value) {
      this.get('controller').get(model).set(property, this.store.peekRecord(property, value));
    }
  }
});

// routes/my-route.js

import Ember from 'ember';
import SetBelongsToMixin from 'myApp/mixins/set-belongs-to';

export default Ember.Route.extend(SetBelongsToMixin, {
  model() {
    return this.get('store')find(...);
  }
});

// templates/my-route.hbs

<select onchange={{action (route-action 'setBelongsTo' 'model' 'title') value="target.value"}}>
  {{#each titles as |title|}}
    <option value={{title.id}} selected={{eq title.id model.title.id}}>
      {{title.description}}
    </option>
  {{/each}}
</select>

Option 2: ember-power-select Method

note: ember-route-action-helper add-on is required

some slight differences if using ember-power-select (https://github.com/cibernox/ember-power-select)

// mixins/my-mixin.js

import Ember from 'ember';

export default Ember.Mixin.create({
  actions: {
    setBelongsTo(model, property, value) {
      this.get('controller').get(model).set(property, value);
    }
  }
});

// routes/my-route.js

import Ember from 'ember';
import SetBelongsToMixin from 'myApp/mixins/set-belongs-to';

export default Ember.Route.extend(SetBelongsToMixin, {
  model() {
    return this.get('store')find(...);
  }
});

// templates/my-route.hbs

{{#power-select
  options=titles
  selected=model.title
  onchange=(action (route-action 'setBelongsTo' 'model' 'title'))
  as |title|
}}
  {{title.description}}
{{/power-select}}

Edit 1: The OP makes use of ember-truth-helpers add-on to set the selected option. (Or OP created their own helper for eq.) The first solution here also uses this add-on.

这篇关于通过native select元素更新belongsTo关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆