2016-12-22 135 views
1

我想弄清楚如何在Aurelia製作Flash消息。我創建了一個自定義元素flash-message,並要求它在app.html中,但消息不會更新。如果將其設置爲默認值,它會正確顯示。如何在Aurelia中設置Flash消息?

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; 
    } 
    // ... 
} 

混亂/視圖模型

由於所有的類屬性被認爲是公開的,你甚至都不需要setMessage(newValue)方法。您可以從object-detail.js更新消息屬性是這樣的:

this.flash.message = 'Activate'; 

此外,@bindable行的目的是使用,讓您可以在HTML代碼中的變量值初始化它,就像這樣:

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

如果你不打算像這樣使用它,我會跳過整個@bindable行。你flash-message.js可以簡化爲僅僅這一點:對Flash的消息

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

使用事件聚合的

我實現了有類似目標的一個Flash Message類,使用Toastr第三方庫(只是因爲我喜歡UI)。但是,以任何你想要的方式設置它並不難。我相信,允許應用程序的任何部分設置Flash消息的最佳方法是使用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實現:

給你做了什麼一樣,我在src文件夾中創建名爲在一個名爲commonFlashMessage一個共同的類。

//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" 
        ] 
       }, 

最後的想法

另請參閱阿什利格蘭特的用於獲取關於您的視圖模型一個手柄以及工作GistRun來立即解決問題的一個更好的解釋迴應。阿什利比我在奧裏利亞更有經驗,所以如果我的解決方案的某些部分不起作用,他很可能會! :-)

+2

如果你想採取我發佈的答案,並將其添加到你的感覺免費。 –

+0

謝謝,你太客氣了!我感謝你爲像我這樣的「小傢伙」留下一些空間來學習和成長!如果您在完全編輯的回覆中看到任何錯誤或誤導性內容,請通知我。 – LStarky

3

我建議使用view-model.ref="flash"來獲取對自定義元素的ViewModel的引用。請注意,您將無法使用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