簡體   English   中英

ember-power-select自定義搜索操作,並使用外部數據“選擇”

[英]ember-power-select Custom Search Action and 'selected' with external data

概觀

我在Ember.js 3.8項目中使用ember-power- select-一半有效,一半無效!

為了使問題更具可讀性,我將所有代碼都放在了問題的底部。

情況

選擇配置為從API端點獲取數據,並向用戶提供一組可能的選項供您選擇。

所涉及的路線(routes / guest / new-using-ember-power-select.js)對模型(models / guest.js)進行createRecord ,然后理想地對兩個表單元素(templates / guests)進行更改/new-using-ember-power-select.js和模板/組件/guest-form-ember-power-select.hbs)反映回數據存儲區中的該記錄中。

問題

這對於文本輸入來說很好用,但是我不能使它適用於ember-power-select。

在當前配置(如下所示)中,用戶可以:

  • 搜索選擇的選項;
  • 選擇一個選項;
  • 將該選擇反映回數據存儲區中的guest實例。 但是,所做的選擇不會反映在用戶界面中-似乎沒有做出選擇

我真的很感謝有人指出我在這里做錯了。 我覺得這可能是一件很小的事情,但是我確實想到,我必須通過組件中的屬性來管理選擇狀態,並且只有在提交表單時才更新基礎數據存儲.....不想這樣做,但是我很想知道這是否被認為是最好的主意。

謝謝


編輯1:我忘了說我已經嘗試過更改ember-power-select的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);
        },
    }
});

我將回答顯示一些差異,以使選擇在您的存儲庫中起作用: https : //github.com/shearichard/emberjs-select-addon-comparison

要了解的關鍵是,在您的情況下,ember-power-select會收到一個塊

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

該塊將被調用以呈現每個選項以及所選選項。 在這種情況下,選項是具有以下形狀的國家對象: {"name":"American Samoa","alpha2Code":"AS"} 這就是為什么您調用{{country.name}}進行渲染的原因。 但是,使用您的方法,您傳遞的所選值不是具有name屬性的對象。 實際上甚至不是對象,在美屬薩摩亞的情況下,它甚至是字符串“ AS”,因此您可以輸出字符串的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 Select文檔,了解使用optionssearch之間的區別:

在這種情況下,您可以提供搜索動作,而不是選項(這是唯一的選項不是必需的情況),只要用戶在搜索框中鍵入內容,該選項就會隨搜索項一起調用。

[...]

關於此操作,您僅需了解三件事:-您應該返回一個集合或一個承諾,該承諾或承諾可以通過此操作解決為一個集合。 -您可以同時提供選項和搜索操作。 這些選項將是初始選項集,但是一旦用戶執行搜索,就會顯示該搜索的結果。

因此,如果您使用options或從search操作返回集合,則對您的問題沒有影響。 歸結為具有selected值,該selected值不是綁定到options或由search操作返回的集合的一部分。

這實際上就是使用onchange=(action (mut item.nationality)) UI能夠按預期工作的原因。 在這種情況下, item.nationalitysearch返回的集合中選定對象的對象(例如{"name":"New Zealand","alpha2Code":"NZ"} ),而不是其alpha2Code屬性的值。

我在答案中使用尖括號組件調用語法 希望很好。 我認為它更易於閱讀。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM