如何在整个 Angular 2 应用程序中保持对话框的状态? [英] How can I maintain the state of dialog box with progress all over my Angular 2 application?

查看:16
本文介绍了如何在整个 Angular 2 应用程序中保持对话框的状态?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

即使我关闭对话框,我也希望保持 Md 对话框的状态.这样我就可以在整个应用程序中保持上传状态处于活动状态.我的计划是将上传响应存储在服务中以维护上传进度,并且工具栏中会给出一个图标.对话框每次重新初始化.如何在整个应用程序中保持上传进度对话框的状态?

I would like to keep the state of the Md Dialog alive even I close the dialog.So that I can keep the upload status active all over the application. My plan is to store the upload response in the service to maintain the upload progress and an icon will be given in the toolbar.The dialog box reinitializes everytime. How can I maintain the state of dialog box with upload progress all over the application?

import { Component, NgZone, Inject, EventEmitter } from '@angular/core';
import { NgUploaderOptions, UploadedFile, UploadRejected } from 'ngx-uploader';
import { MdDialog, MdDialogRef, MdDialogConfig } from '@angular/material';
import { Router } from '@angular/router';
import { UploadService } from './upload.service';
import './operators';

@Component({
  moduleId: module.id,
  selector: 'sd-app',
  templateUrl: 'app.component.html',
})
export class AppComponent {
  temp:any;
  dialogRef: MdDialogRef<DialogComponent>;
  config: MdDialogConfig = {
    disableClose: true
  };
  constructor(public dialog: MdDialog, private router: Router, public uploadService: UploadService ) {
  this.temp = this.uploadService.getUpload();
  }

  openDialog() {
    this.dialogRef = this.dialog.open(DialogComponent, this.config);
  }


}

app.component.html

 <md-progress-bar mode="determinate"
                       [value]="temp.progress.percent"
                       color="primary"
                       class="progress-bar-margins">
      </md-progress-bar>
      <span>{{temp.progress.percent}}%</span>

对话框组件

export class DialogComponent {
  options: NgUploaderOptions;
  response: any;
  sizeLimit: number = 1024 * 1024 * 50; // 50MB
  previewData: any;
  errorMessage: string;
  inputUploadEvents: EventEmitter<string>;
  temp:any;
  constructor(@Inject(NgZone) private zone: NgZone, public uploadService: UploadService) {

    this.options = new NgUploaderOptions({
        url: 'http://api.ngx-uploader.com/upload',
        filterExtensions: false,
        allowedExtensions: ['dsn'],
        data: { userId: 12 },
        autoUpload: false,
        fieldName: 'file',
        fieldReset: true,
        maxUploads: 2,
        method: 'POST',
        previewUrl: true,
        withCredentials: false
    });

    this.inputUploadEvents = new EventEmitter<string>();
  }
  startUpload(view:any) {
    this.inputUploadEvents.emit('startUpload');
  }
  beforeUpload(uploadingFile: UploadedFile): void {
    if (uploadingFile.size > this.sizeLimit) {
      console.log('File is too large!');
      this.errorMessage = 'File is too large! Please select valid file';
      uploadingFile.setAbort();
    }
  }

  handleUpload(data: any) {
      setTimeout(() => {
        this.zone.run(() => {
          this.response = data;
          this.uploadService.uploadData = data;
          this.temp = this.uploadService.getUpload();
          if (data && data.response) {
            this.response = JSON.parse(data.response);
          }
        });
      });
    }

    handlePreviewData(data: any) {
    this.previewData = data;
  }
  }

upload.component.html

 <button type="button" class="start-upload-button" (click)="startUpload()">Start Upload</button>
</div>
< <div *ngIf="previewData && !response">
  <img [src]="previewData">
</div> 
<div>
 <md-progress-bar mode="determinate"
        [value]="temp.progress.percent"
        color="primary"
        class="progress-bar-margins">
        </md-progress-bar>
        <span>{{temp.progress.percent}}%</span>
</div>

<<div *ngIf="previewData && !response"><img [src]="previewData">

upload.service.ts

<div><md-progress-bar mode="确定"[值]="temp.progress.percent"颜色=主要"class="progress-bar-margins"></md-progress-bar><span>{{temp.progress.percent}}%</span>

import { Injectable } from '@angular/core'; import { BehaviorSubject } from 'rxjs/Rx'; import { Observable } from 'rxjs'; import { Subject } from 'rxjs/Rx'; @Injectable() export class UploadService { uploadData :any; constructor() { console.log('Global Service initialised'); } getUpload() { return this.uploadData; } }

upload.service.ts

Use the flux architectural pattern for building UI interfaces:

推荐答案

使用 Flux 架构模式构建 UI 界面:

The idea is simple - in a flux architecture, data always flows in one direction:

这是真的,即使是从 UI 触发的操作:

This is true, even when there is an action triggered from the UI:

在您的 Angular2 应用程序中,调度程序是在您的服务上实现的 Observable(任何注入服务的组件都可以订阅它),而存储是数据的缓存副本,以帮助发出事件.

In your Angular2 application, the dispatcher are your Observables implemented on your service (any component that injects the service can subscribe to it) and the store is a cached copy of the data to aid in emitting events.

以下是实现 Flux 架构的 ToDoService 示例:

Here is an example of a ToDoService that implements the Flux architecture:

import { Injectable } from '@angular/core';
import {Http } from '@angular/http';
import { BehaviorSubject, Observable } from 'rxjs/Rx';
import 'rxjs/add/operator/toPromise';

export interface ToDo {
    id: number;
    name:string;
    isComplete: boolean;
    date: Date;
}

@Injectable()
export class ToDoService {
    public todoList$:Observable<ToDo[]>;
    private subject: BehaviorSubject<ToDo[]>;
    private store: {
        todos: ToDo[];
    }

    public constructor(private http:Http) { 
        this.subject = new BehaviorSubject<ToDo[]>([]);
        this.todoList$ = this.subject.asObservable();
        this.store = {
            todos: []
        };
    }

    public remove(todo:ToDo) {
        this.http.delete(`http://localhost/todoservice/api/todo/${todo.id}`)
            .subscribe(t=> {
                this.store.todos.forEach((t, i) => {
                    if (t.id === todo.id) { this.store.todos.splice(i, 1); }
                });
                let copy = this.copy(this.store).todos;
                this.subject.next(copy);

            });
    }

    public update(todo:ToDo): Promise<ToDo> {
        let q = this.http.put(`http://localhost/todoservice/api/todo/${todo.id}`, todo)
            .map(t=>t.json()).toPromise();
        q.then(x=> {

                this.store.todos.forEach((t,i) => {
                    if (t.id == x.id) { Object.assign(t, x); }
                    let copy = this.copy(this.store).todos;
                    this.subject.next(copy);
                });
            });
        return q;

    }

    public getAll() {
        this.http.get('http://localhost/todoservice/api/todo/all')
            .map(t=>t.json())
            .subscribe(t=> {
                this.store.todos = t;
                let copy = Object.assign({}, this.store).todos;
                this.subject.next(copy);

            });
    }

    private copy<T>(t:T):T {
        return Object.assign({}, t);
    }

}

关于此服务有几点需要注意:

There are several things to notice about this service:

  • 服务存储数据存储的缓存副本{ todos: ToDo[] }
  • 它公开了一个组件可以订阅的 Observable(如果他们感兴趣的话)
  • 它使用一个 BehaviourSubject,它的实现是私有的.一个 BehaviorSubject 在订阅时会发出一个初始值.如果你想用一个空数组开始初始化 Observable,这很方便.
  • 每当调用改变数据存储(删除或更新)的方法时,该服务都会调用 Web 服务来更新其持久存储,然后在发出更新的 ToDo[]<之前更新其缓存的数据存储/code> 列出所有订阅者
  • 从服务中发出数据的副本,以防止意外的数据更改沿相反方向传播(这对于维持通量模式很重要).

任何 DI 注入服务的组件都有机会订阅 todoList$ observable.

Any component that DI injects the Service has an opportunity to subscribe to the todoList$ observable.

在以下组件中,我们利用异步管道而不是直接订阅 todoList$ observable:

In the following component, we take advantage of the async pipe instead of subscribing to the todoList$ observable directly:

Component.ts

ngOnInit() {
    this.todoList$ = this.todoService.todoList$;
}

Component.html

<li class="list-group-item" *ngFor="let item of todoList$ | async">
     {{ item.name }}
</li>

每当在服务上调用修改其内部存储的方法时,该服务都会更新其所有组件订阅者,无论哪个组件发起更改.

Whenever a method is called on the service that modifies its internal store, the service updates all of its component subscribers, regardless of which component initiated the change.

Flux 模式是管理复杂 UI 和减少组件之间耦合的绝佳模式.相反,耦合是在Service和Component之间,交互主要是为了组件订阅服务.

The Flux pattern is an excellent pattern for managing complex UIs and reducing the coupling between components. Instead, the coupling is between the Service and the Component, and the interaction is mainly for the component to subscribe to the service.

这篇关于如何在整个 Angular 2 应用程序中保持对话框的状态?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆