余烬电源选择自定义搜索操作并使用外部数据进行'selected'



概述

我在ember.js 3.8项目中使用ember-power-select - 一半工作,一半否!

使问题更可读性,我将所有代码都放在问题的底部。

情况

选择已配置为从API端点获取数据,并为用户提供一组可能的选项。

所涉及的路由(路由/访客/新inder-ember-power-select.js(进行了模型的 createRecord(型号/guest.js(,然后,理想情况下,对两个元素进行了更改(模板/guest/new-using-ember-power-select.js和模板/组件/guest-form-ember-ember-power-select.hbs(在数据存储中反射回该记录。

essue

这适用于文本输入,但我无法使其适用于Ember-Power-Select。

在当前配置(如下所示(中,用户可以:

  • 搜索选择选项;
  • 选择一个选项和;
  • 将选择反射回数据存储中的guest实例。但是,选择的选择并未反映在用户界面中 - 似乎没有选择

我真的很感激有人指出我在这里做错了什么。我觉得这可能是一件很小的事情宁愿不这样做,但我很想知道这是否被认为是最好的主意。

谢谢


编辑1:我忘了说我试图更改ember-power选择的 onchange属性,以便看起来不像这样

onchange=(action "nationalityChangeAction")

...看起来像这样...

onchange=(action (mut item.nationality))

具有:

的效果
  • 所选值以表格可见(您通常会期望,但与我当前的努力不同(,但是
  • 放置在基础数据存储记录中的值不是两个字符乡村代码,而是一个数组的实例返回API调用,一个具有两个属性{"name":"New Zealand","alpha2Code":"NZ"}的对象。

模型

//app/models/guest.js
import DS from 'ember-data';
import { validator, buildValidations } from 'ember-cp-validations';
const Validations = buildValidations({
  name: [
    validator('presence', true),
  ],
  nationality: [
    validator('presence', true),
  ],
});

export default DS.Model.extend( Validations, {
  name: DS.attr('string'),
  nationality: DS.attr('string')
});

路由

//app/routes/guest/new-using-ember-power-select.js
import Route from '@ember/routing/route';
export default Route.extend({
  model() {
    return this.store.createRecord('guest', {
      name: "",
      nationality: ""
    });
  },
  actions: {
    updateNationality(slctnValue) {
      this.controller.model.set('nationality' , slctnValue);
    },
  }
});

模板

//app/templates/guests/new-using-ember-power-select.js
<h2>Guest: Add New</h2>
<div class="well well-sm">
  Demonstration of 'ember-power-select'
</div>
{{guest-form-ember-power-select
  item=model
  changeNationalityHandler="updateNationality"
  updateRecordHandler="updateRecord"
  cancelHandler="cancelAndExit"
}}
{{outlet}}

组件模板

//app/templates/components/guest-form-ember-power-select.hbs
<div class="form-vertical">
  {{!-- Guest Name --}}
  <div class="form-group">
    <label class="control-label">Name</label>
    <div class="">
      {{  input type="text"
          value=item.name
          class="form-control"
          placeholder="The name of the Guest"
          focus-out=(action (mut this.errMsgDspCntrl.nameError) true)
      }}
    </div>
    {{#if this.errMsgDspCntrl.nameError}}
      <div class="text-danger">
        {{v-get item 'name' 'message'}}
      </div>
    {{/if}}
  </div>
  <div class="form-group">
    <label class="control-label">Countries (using power-select)</label>
    <div class="">
      {{#power-select
        searchPlaceholder="Text to provide user info about what they can search on"
        search=(action "searchCountries")
        selected=item.nationality
        onchange=(action (mut item.nationality))
        as |countries|
      }}
        {{countries.name}}
      {{/power-select}}
    </div>
    {{#if this.errMsgDspCntrl.nationalityError}}
      <div class="text-danger">
        {{v-get item 'nationality' 'message'}}
      </div>
    {{/if}}
  </div>
  {{!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--}}
  {{!-- Buttons --}}
  <div class="form-group">
    <div class="">
      <button type="submit" class="btn btn-default" {{action "buttonSaveClicked" item}}>{{buttonLabel}}</button>
      <button type="button" class="btn btn-default" {{action "buttonCancelClicked" item}} >Cancel</button>
    </div>
  </div>
</div>
{{yield}}

组件

//app/components/guest-form-ember-power-select.js
import Component from '@ember/component';
export default Component.extend({
    actions:{
        searchCountries(term) {
          //Response to :
          //
          //https://restcountries.eu/rest/v2/name/z?fields=name;alpha2Code
          //
          //
          //looks like this
          //  [
          //    ...
          //    {"name":"New Zealand","alpha2Code":"NZ"}
          //    ...
          //  ]
          //
          let url = `https://restcountries.eu/rest/v2/name/${term}?fields=name;alpha2Code`
          let dbg = fetch(url)
            .then(function(response) {
              return response.json();
            });
          return dbg;
        },
        nationalityChangeAction(slctn){
            this.sendAction('changeNationalityHandler', slctn.alpha2Code);
        },
    }
});

我将回答一些差异,并在您的回购中进行选择所需的更改:select-addon-comparparison

要理解的关键是,在您的情况下,Ember-Power-Select会收到一个块

as |country|}}
  {{country.name}}
{{/power-select}}

该块将被调用以渲染每个选项,也将呈现选定的选项。在这种情况下,选项是具有此形状的国家对象:{"name":"American Samoa","alpha2Code":"AS"}。这就是为什么您调用{{country.name}}渲染它的原因。但是,使用您的方法,您传递的选定值不是具有名称属性的对象。实际上,甚至不是一个对象,而是字符串"为",因此您可以输出字符串的名称属性。

在您的情况下,您存储的信息(国家代码(不足以在选择的扳机中显示出一个不错的"美国萨摩亚",并且由于您在搜索搜索之前不知道这些国家您无法使用该国家代码来查看国家。

如果您没有编辑表格,我的建议是将整个选定的国家存储在您传递给selected的属性中。

diff --git a/app/components/guest-form-ember-power-select.js b/app/components/guest-form-ember-power-select.js
index edf9390..2467d85 100644
--- a/app/components/guest-form-ember-power-select.js
+++ b/app/components/guest-form-ember-power-select.js
@@ -25,6 +25,8 @@ export default Component.extend({
   //messages
   nameOfErrMsgDspCntrl : 'errMsgDspCntrl',
+  nationality: undefined,
+
   actions:{
     searchCountries(term) {
@@ -73,7 +75,7 @@ export default Component.extend({
     },
     nationalityChangeAction(slctn){
-      //this.set(this.myValue, slctn);
+      this.set('nationality', slctn);
       this.sendAction('changeNationalityHandler', slctn.alpha2Code);
     },
diff --git a/app/templates/components/guest-form-ember-power-select.hbs b/app/templates/components/guest-form-ember-power-select.hbs
index 56f007d..5c69834 100644
--- a/app/templates/components/guest-form-ember-power-select.hbs
+++ b/app/templates/components/guest-form-ember-power-select.hbs
@@ -24,7 +24,7 @@
       {{#power-select
         searchPlaceholder="Text to provide user info about what they can search on"
         search=(action "searchCountries")
-        selected=item.nationality
+        selected=nationality
         onchange=(action "nationalityChangeAction")
         as |countries|
       }}
@@ -36,14 +36,14 @@

,只要您不想编辑您以前创建的用户的国籍,甚至几周前。在这种情况下,您不会提及该国,只有国家代码。在这种情况下,我建议将selected作为计算属性,如果您的API允许,则将其诺言带有用户国家代码的国家对象的承诺。似乎确实如此,所以最好的解决方案是

diff --git a/app/components/guest-form-ember-power-select.js b/app/components/guest-form-ember-power-select.js
index edf9390..f889734 100644
--- a/app/components/guest-form-ember-power-select.js
+++ b/app/components/guest-form-ember-power-select.js
@@ -1,4 +1,5 @@
 import Component from '@ember/component';
+import { computed } from '@ember/object';
 export default Component.extend({
   buttonLabel: 'Save',
@@ -25,6 +26,16 @@ export default Component.extend({
   //messages
   nameOfErrMsgDspCntrl : 'errMsgDspCntrl',
+  nationality: computed('item.nationality', function() {
+    let countryCode = this.get('item.nationality');
+    if (countryCode) {
+      return fetch(`https://restcountries.eu/rest/v2/alpha/${countryCode}?fields=name;alpha2Code`)
+        .then(function (response) {
+          return response.json();
+        });
+    }
+  }),
+

这最后一个将为您知道的国家提供信息。

selected属性必须是提供给Ember Power Select的选项中的元素。在您的情况下,您不使用options属性,而是通过search操作设置选项,但这并没有很大的不同。

您的搜索操作返回对象数组(例如[{"name":"New Zealand","alpha2Code":"NZ"}](。nationalityChangeActionselected值设置为alpha2Code的值。因此,selected不包括在选项中:

[{"name":"New Zealand","alpha2Code":"NZ"}].includes('NZ') // false

因此,您的权力选择的状态与此相似:

<PowerSelect
  @options={{array
    (hash foo="bar")
  }}
  @selected="bar"
/>

您正在做的事情看起来像这样的简化版本:

<PowerSelect
  @options={{array
    (hash foo="bar")
  }}
  @selected={{selected}}
  @onchange={{action (mut selected) value="foo"}}
/>

请在Ember Power中查看有关使用optionssearch之间的差异的文档:

在这种情况下,您可以提供搜索操作而不是选项(这是唯一不强制性选项的情况(,只要用户在搜索框上键入搜索词时,就会使用搜索词调用。

[...]

关于此动作只有三件事: - 您应该退还从此操作中解决的收集或承诺。 - 您可以提供选项和搜索操作。这些选项将是初始选项集,但是一旦用户执行搜索,该搜索的结果将被显示。

因此,如果您使用options或从search操作返回集合,则不会对您的问题产生影响。这一切都归结为具有与options绑定或由search Action返回的selected值。

这实际上是如果使用onchange=(action (mut item.nationality)),您的UI正常工作的原因。在这种情况下,item.nationalitysearch返回的集合中所选对象(例如{"name":"New Zealand","alpha2Code":"NZ"}(,而不是其alpha2Code属性的值。

我在答案中使用角度支架组件调用语法。希望那很好。我认为它更容易阅读。

最新更新