2016-12-22 4 views
1

Я пытаюсь выяснить, как сделать флеш-сообщения в Аурелии. Я создал пользовательский элемент flash-message и потребовал его в app.html, но сообщение не обновляется. Он правильно отображает, если я устанавливаю его по умолчанию.Как установить Flash-сообщения в Aurelia?

app.html

<template> 
    <require from="./resources/elements/flash-message"></require> 
    <flash-message></flash-message> 
</template> 

флэш-message.html

<template> 
    <div class="alert alert-success">${message}</div> 
</template> 

флеш-message.js

import {bindable, bindingMode} from 'aurelia-framework'; 

export class FlashMessage { 
    @bindable({defaultBindingMode: bindingMode.twoWay}) message = 'Default'; 

    setMessage(newValue) { 
    this.message = newValue; 
    } 
} 

объектного detail.js

import {FlashMessage} from './resources/elements/flash-message'; 

export class ObjectDetail { 
    static inject() {return [FlashMessage]}; 

    constructor(flash) { 
    this.flash = flash; 
    } 

    activate(params, routeConfig) { 
    this.flash.setMessage('Activate'); 
    } 
} 

activate() код вызываются, а также setMessage() метод, но отображаемые обменивались сообщения не обновляется. Что мне не хватает?

+1

Поскольку пользовательские элементы создаются с несколькими экземплярами, вы работаете с двумя разными экземплярами 'FlashMessage', поэтому свойства одного не отражаются в другом. – LStarky

ответ

4

Поскольку вам требуется только шаблон в app.html без создания экземпляра класса в app.js, Aurelia рассматривает его как пользовательский элемент, что означает, что у него есть свой экземпляр (а не один). Вы в основном работаете с двумя разными экземплярами FlashMessage, поэтому свойства одного не отражены в другом.

Если вы хотите, чтобы он был создан как одноэлементный класс, вам также нужно будет импортировать компонент в app.js и ввести его в конструктор, чтобы он обрабатывался как компонент, а не пользовательский элемент.

app.js

import {FlashMessage} from './resources/elements/flash-message'; 

@inject(FlashMessage) 
export class App { 
    constructor(flashMessage) { 
    this.flashMessage = flashMessage; 
    } 
    // ... 
} 

Путаница между пользовательских элементов и класса/ViewModel

Поскольку все свойства класса считаются общедоступным, не нужно даже метод setMessage(newValue). Вы можете обновить свойство сообщения от object-detail.js как это:

this.flash.message = 'Activate'; 

Также @bindable линии предназначена для использования, так что вы можете создать его экземпляр с переменным значением в HTML-коде, например:

<flash-message message="Show this message"></flash-message> 

Если вы не планируете использовать его так, я бы пропустил всю линию @bindable. Ваш flash-message.js может быть упрощена только это:

export class FlashMessage { 
    constructor() { 
    this.message = 'Default'; 
    } 
} 

Использование событий агрегатором для Flash-сообщения

я реализовал класс флэш-сообщение с аналогичными целями, с использованием библиотеки Toastr 3 участника (только потому, что мне понравилось пользовательский интерфейс). Но это не сложно настроить так, как вы хотите.Я считаю, что лучший подход, позволяющий любой части вашего приложения установить флеш-сообщение, - это использовать агрегатор событий Aurelia. Следующий фрагмент кода может помочь вам настроить его.

флеш-message.js

import { inject } from 'aurelia-framework' 
import { EventAggregator } from 'aurelia-event-aggregator'; 

@inject(EventAggregator) 
export class FlashMessage { 

    constructor(eventAggregator) { 
    this.eventAggregator = eventAggregator; 
    this.eventAggregator.subscribe('ShowFlashMessage', this.showMessage); 
    } 

    showMessage(message) { 
    this.message = message; 
    // hide after 10 seconds 
    window.setTimeout(hideMessage, 10000); 
    } 

    hideMessage() { 
    this.message = ""; 
    } 
} 

Это, очевидно, упрощена и не обрабатывает несколько сообщений, или возобновлять таймер, когда второе сообщение отправлено, но оно должно быть достаточно, чтобы вы начали ,

Чтобы установить сообщение из другой части вашего приложения, вы можете просто первый впрыскивать eventAggregator и сохранить в конструкторе, а затем опубликовать сообщение вроде этого:

this.eventAggregator.publish('ShowFlashMessage', "Record saved"); 

Моего Toastr Реализация в Aurelia:

Подобно тому, что вы сделали, я создал общий класс под названием FlashMessage в подпапку под названием common в моей src папке.

//src/common/flash-message.js 
import * as toastr from 'toastr'; 
import { inject } from 'aurelia-framework' 
import { EventAggregator } from 'aurelia-event-aggregator'; 

@inject(EventAggregator) 
export class FlashMessage { 

    constructor(eventAggregator) { 
     this.eventAggregator = eventAggregator; 
     this.eventAggregator.subscribe('ewFlashSuccess', this.showSuccess); 
     this.eventAggregator.subscribe('ewFlashInfo', this.showInfo); 
     this.eventAggregator.subscribe('ewFlashWarning', this.showWarning); 
     this.eventAggregator.subscribe('ewFlashError', this.showError); 

     // Not sure why this is not working... if you figure it out, let me know. 
     toastr.options = { 
      positionClass: "toast-top-left", 
      showEasing: "swing", 
      hideEasing: "linear", 
      showMethod: "fadeIn", 
      hideMethod: "fadeOut", 
      preventDuplicates: true, 
      closeButton: true 
     } 
    } 

    showSuccess(message) { 
     toastr.success(message, null, {preventDuplicates: true, closeButton: true}); 
    } 

    showInfo(message) { 
     toastr.info(message, null, {preventDuplicates: true, closeButton: true}); 
    } 

    showWarning(message) { 
     toastr.warning(message, null, {preventDuplicates: true, closeButton: true}); 
    } 

    showError(message) { 
     toastr.error(message, null, {preventDuplicates: true, closeButton: true}); 
    } 

} 

Затем я впрыскивается и инстанцировали его в app.js, как это:

import { inject } from 'aurelia-framework'; 
import { FlashMessage } from './common/flash-message'; 
@inject(Core, FlashMessage) 
export class App { 
    constructor(core, flashMessage) { 
    this.flashMessage = flashMessage; 
    } 
    // ... 
} 

Я также должен был требовать CSS в app.html так:

<require from="toastr/build/toastr.min.css"></require> 

Все это зависит от того, с установленным Toastr (я установил его с npm install toastr --save) и правильно потребовался в качестве зависимости в aurelia.json (Я использую CLI).

   { 
        "name": "toastr", 
        "path": "../node_modules/toastr", 
        "main": "toastr", 
        "resources": [ 
         "build/toastr.min.css" 
        ] 
       }, 

Заключительные мысли

Также см ответ Эшли Гранта для лучшего объяснения получить ручку на вашей ViewModel, а также рабочую GistRun, чтобы исправить свои неотложные вопросы. Эшли гораздо более опытная, чем я с Aurelia, поэтому, если части моего решения не работают, скорее всего, это будет! :-)

+2

Если вы хотите принять ответ, который я разместил, добавьте его в свое свободное время. –

+0

Спасибо, ты слишком добрый! Я ценю, что вы оставляете место для «маленьких парней», таких как я, чтобы учиться и расти! Если вы видите что-либо в моем полностью отредактированном ответе, который является неправильным или вводящим в заблуждение, сообщите мне. – LStarky

3

Я бы рекомендовал получить ссылку на ViewModel настраиваемого элемента, используя view-model.ref="flash". Обратите внимание, что вы не сможете использовать это из обратного вызова activate, хотя, поскольку в этой точке жизненного цикла страницы не было никакой привязки. Я использую обратный вызов attached в моем примере ниже.

Вот пример: https://gist.run?id=76ef47a5327a34560737f4ade1038305

app.html

<template> 
    <require from="./flash-message"></require> 
    <flash-message view-model.ref="flash"></flash-message> 
</template> 

app.js

export class App { 
    attached(params, routeConfig) { 
    this.flash.setMessage('Activate'); 
    } 
} 

флэш-сообщение.HTML

<template> 
    <div class="alert alert-success">${message}</div> 
</template> 

флеш-message.js

import {bindable, bindingMode} from 'aurelia-framework'; 

export class FlashMessage { 
    @bindable({defaultBindingMode: bindingMode.twoWay}) message = 'Default'; 

    setMessage(newValue) { 
    this.message = newValue; 
    } 
} 
3

Из сообщения LStarky, я обнаружил toastr, которую я не знал раньше, так что я в конечном итоге только с помощью этой библиотеки вместо этого.

npm install toastr --save

aurelia.json (Под расслоении -> зависимостей)

{ 
    "name": "toastr", 
    "path": "../node_modules/toastr", 
    "main": "toastr", 
    "resources": [ 
    "build/toastr.min.css" 
    ] 
} 

app.html

<require from="toastr/build/toastr.min.css"></require> 

вид-model.js

import toastr from 'toastr'; 

action() { 
    toastr.success('Toastr visible!'); 
} 
+1

Да, это то, что я бы рекомендовал, честно :-) Привет! –

+0

Рад, что вы нашли решение! – LStarky