[英]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))
其結果是:
{"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"}]
)。 nationalityChangeAction
將selected
值設置為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文檔,了解使用options
和search
之間的區別:
在這種情況下,您可以提供搜索動作,而不是選項(這是唯一的選項不是必需的情況),只要用戶在搜索框中鍵入內容,該選項就會隨搜索項一起調用。
[...]
關於此操作,您僅需了解三件事:-您應該返回一個集合或一個承諾,該承諾或承諾可以通過此操作解決為一個集合。 -您可以同時提供選項和搜索操作。 這些選項將是初始選項集,但是一旦用戶執行搜索,就會顯示該搜索的結果。
因此,如果您使用options
或從search
操作返回集合,則對您的問題沒有影響。 歸結為具有selected
值,該selected
值不是綁定到options
或由search
操作返回的集合的一部分。
這實際上就是使用onchange=(action (mut item.nationality))
UI能夠按預期工作的原因。 在這種情況下, item.nationality
是search
返回的集合中選定對象的對象(例如{"name":"New Zealand","alpha2Code":"NZ"}
),而不是其alpha2Code
屬性的值。
我在答案中使用尖括號組件調用語法 。 希望很好。 我認為它更易於閱讀。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.