Получение свойств компонента ember из класса компонентов ember

Я пытался получить значение свойства компонента из действия из его класса. Моя основная цель — связать два объекта: аукцион перешел в мой компонент (показан в коде ниже)

new.hbs

<AuctionForm 
    @auction={{@model.auction}}
    @products={{@model.products}}/>

с выбранным продуктом в теге select внутри компонента AuctionForm следующим образом:

аукцион-form.hbs

<div class="row">
    <label for="product">Produto</label>
    <select name="product" onchange={{action 'selectProduct' value='target.value'}}>
        <option value="" selected='selected' disabled='disabled'>-------</option>
        {{#each @products as |product|}}
            <option value="{{product.id}}" selected={{if (equalstr product.id @auction.product.id) 'selected'}}>{{product.name}}</option>
        {{/each}}
    </select>
</div>

и я хочу связать эти два объекта с действием selectProduct класса:

аукцион-form.js

import Component from '@glimmer/component';
import { action } from '@ember/object';


export default class AuctionFormComponent extends Component {
    @action selectProduct(product) {
        this.get('auction').set('product', product); // this doesn't work on ember newest version
    }
    @action save(auction) {
        auction.save();
    }
}

Хотя всякий раз, когда я пытаюсь получить доступ к его значению в классе-компоненте через функцию this.get() (так же, как я делал это в предыдущих версиях Ember), я получаю сообщение об ошибке, говорящее, что this.get не является функцией.

После долгих поисков в Интернете я не смог найти ни простого решения, ни официального решения, предоставленного документацией.

Самое близкое к решению, которое я нашел, было объявить аукцион как вычисляемое свойство (https://api.emberjs.com/ember/3.22/classes/Component). Но мне не удалось реализовать его в файле javascript, поскольку его структура (например, код ниже) работает только с файлами TypeScript.

import Component from '@glimmer/component';
import { action } from '@ember/object';
import { computed } from '@ember/object';


export default class AuctionFormComponent extends Component {
    auction: computed('auction', function() {
        return this.auction;
    }
    @action selectProduct(product) {
        debugger;
        this.get('auction').set('product', product);
    }
    @action save(auction) {
        auction.save();
    }
}

Кто-нибудь знает, как правильно выполнить такую ​​задачу в ember 3.22?

Спасибо большое.


person B Porto    schedule 02.12.2020    source источник


Ответы (1)


Поскольку вы используете современные компоненты Glimmer (импортированные из @glimmer/component),

  1. Доступ к аргументам должен осуществляться через args свойство внутри класса js, например, this.args.auction.

  2. Аргументы (auction и products) не изменяются внутри компонента. Чтобы изменить значение аргумента, мы можем отправить действие родительскому элементу для изменения значения.

  3. Методы get и set недоступны в компонентах мерцания. Эти методы являются частью классического компонента ember. Вы можете получить доступ к свойствам класса, просто используя запись с точкой [.], например: this.auction, и переназначить значения, используя оператор присваивания, например this.property = 'value'

  4. Поскольку вы используете собственный синтаксис класса, action: computed(..) не является допустимым объявлением.

  5. Для привязки событий рекомендуется использовать модификатор on и fn помощник

Объединив все точки,

import Component from '@glimmer/component';
import { action } from '@ember/object';

export default class AuctionFormComponent extends Component {
    @action 
    selectProduct(event) {
        // This `updateProduct` has to be implemented in parent class 
        // which mutates the `auction` object.
        this.args.updateProduct(event.target.value); // -> `on` modifier will capture the native event
    }

    @action 
    save(auction) {
        auction.save();
    }
}
<div class="row">
    <label for="product">Produto</label>
    <select name="product" {{on "change" this.selectProduct}}>
        <option value="" selected='selected' disabled='disabled'>-------</option>
        {{#each @products as |product|}}
            <option value="{{product.id}}" selected={{if (equalstr product.id @auction.product.id) 'selected'}}>{{product.name}}</option>
        {{/each}}
    </select>
</div>

и вызов будет выглядеть так:

<AuctionForm 
    @auction={{@model.auction}}
    @products={{@model.products}}
    @updateProduct={{this.updateProduct}}
/>

Здесь необходимо правильно реализовать updateProduct для обновления продукта.


EDIT: Как упоминалось в комментарии @BPorto, это Шпаргалка по миграции Ember Octane будет полезна при переносе кодовой базы с классической модели Ember на модель Octane.

person Gokul Kathirvel    schedule 02.12.2020
comment
Большое спасибо за разъясняющий ответ, получилось очень хорошо. - person B Porto; 02.12.2020
comment
Если кто-то пытается перейти с предыдущих версий Ember на новую (как и я), вот ссылка с очень полезным сравнением между Ember и Ember Octane. Надеюсь, поможет! ссылка - person B Porto; 02.12.2020
comment
Шпаргалка точно будет полезна. добавит его к самому ответу. - person Gokul Kathirvel; 03.12.2020