zoukankan      html  css  js  c++  java
  • Angular4中利用promise异步加载gojs

    GoJS是一个实现交互类图表(比如流程图,树图,关系图,力导图等等)的JS库

    gojs提供了angular的基本例子,不过是离线版

    https://github.com/NorthwoodsSoftware/GoJS/tree/master/projects/angular-basic

    下图是运行结果。上面是可拖动的,下面显示当前图表的结构

    一。首先完成上面可拖动的部分

    diagram-editor

    diagram-editor.component.ts

    constructor中完成初始化图表的基本属性如颜色等

    this.getModel();从服务器获得列表

    this.networkService.getModelText().then(r => { console.log(r); this.createModel(JSON.stringify(r)); });

    r => { } r是获得的数据,括号里面可以添加对数据进行的操作(可以加函数),我获取数据就是完整的json格式的gojs图表,直接string化传给model它就可以识别了,图表格式如下

    { "class": "go.GraphLinksModel",
      "nodeDataArray": [ 
    {"key":1, "text":"Alpha", "color":"lightblue", "loc":"0 0"},
    {"key":2, "text":"Beta", "color":"orange", "loc":"72.09912109375 0"},
    {"key":3, "text":"Gamma", "color":"lightgreen", "loc":"0 70"},
    {"key":4, "text":"Delta", "color":"pink", "loc":"84.40087890625 70"},
    {"text":"Gamma", "color":"lightgreen", "key":-3, "loc":"-138.71875 88.41666412353516"},
    {"text":"Epsilon", "color":"yellow", "key":-5, "loc":"-316.71875 158.41666412353516"}
     ],
      "linkDataArray": [ 
    {"from":1, "to":2},
    {"from":1, "to":3},
    {"from":2, "to":2},
    {"from":3, "to":4},
    {"from":4, "to":1}
     ]}

    然后调用函数createModel,用gojs自带函数go.Model.fromJson显示表格,这样可以实现异步加载图表。

    onSave()保存图表到服务器

    import { Component, OnInit, ViewChild, ElementRef, Input, Output, EventEmitter, AfterContentInit } from '@angular/core';
    import * as go from 'gojs';
    import { NetworkService } from '../network.service';
    import { Observable } from 'rxjs/observable';
    import { catchError, map, tap } from 'rxjs/operators';
    import { interval  } from 'rxjs/observable/interval';
    import {passBoolean} from 'protractor/built/util';
    @Component({
      selector: 'app-diagram-editor',
      templateUrl: './diagram-editor.component.html',
      styleUrls: ['./diagram-editor.component.css']
    })
    export class DiagramEditorComponent implements OnInit {
      private diagram: go.Diagram = new go.Diagram();
      private palette: go.Palette = new go.Palette();
    
    
      @ViewChild('diagramDiv')
      private diagramRef: ElementRef;
    
      @ViewChild('paletteDiv')
      private paletteRef: ElementRef;
    
      @Input()
      get model(): go.Model { return this.diagram.model; }
      set model(val: go.Model) { this.diagram.model = val; }
      @Output()
      nodeSelected = new EventEmitter<go.Node|null>();
    
      @Output()
      modelChanged = new EventEmitter<go.ChangedEvent>();
    
      constructor(private networkService: NetworkService) {
        this.getModel();
        const $ = go.GraphObject.make;
        this.diagram = new go.Diagram();
        this.diagram.initialContentAlignment = go.Spot.Center;
        this.diagram.allowDrop = true;  // necessary for dragging from Palette
        this.diagram.undoManager.isEnabled = true;
        this.diagram.addDiagramListener("ChangedSelection",
          e => {
            const node = e.diagram.selection.first();
            this.nodeSelected.emit(node instanceof go.Node ? node : null);
          });
        this.diagram.addModelChangedListener(e => e.isTransactionFinished && this.modelChanged.emit(e));
    
        this.diagram.nodeTemplate =
          $(go.Node, "Auto",
            new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify),
            $(go.Shape,
              {
                fill: "white", strokeWidth: 0,
                portId: "", cursor: "pointer",
                // allow many kinds of links
                fromLinkable: true, toLinkable: true,
                fromLinkableSelfNode: true, toLinkableSelfNode: true,
                fromLinkableDuplicates: true, toLinkableDuplicates: true
              },
              new go.Binding("fill", "color")),
            $(go.TextBlock,
              { margin: 8, editable: true },
              new go.Binding("text").makeTwoWay())
          );
    
        this.diagram.linkTemplate =
          $(go.Link,
            // allow relinking
            { relinkableFrom: true, relinkableTo: true },
            $(go.Shape),
            $(go.Shape, { toArrow: "OpenTriangle" })
          );
    
        this.palette = new go.Palette();
        this.palette.nodeTemplateMap = this.diagram.nodeTemplateMap;
    
        // initialize contents of Palette
        this.palette.model.nodeDataArray =
          [
            { text: "Alpha", color: "lightblue" },
            { text: "Beta", color: "orange" },
            { text: "Gamma", color: "lightgreen" },
            { text: "Delta", color: "pink" },
            { text: "Epsilon", color: "yellow" }
          ];
      }
    
      ngOnInit() {
        this.diagram.div = this.diagramRef.nativeElement;
        this.palette.div = this.paletteRef.nativeElement;
      }
      getModel(): void {
    
             this.networkService.getModelText().then(r => { console.log(r); this.createModel(JSON.stringify(r)); });
    
    }
    createModel(a: string ): void {
      this.model = go.Model.fromJson(a);
    
    }
      onSave(): void {
        this.networkService.saveModel(this.diagram.model.toJson()).subscribe();
      }
    
    }

    diagram-editor.component.html

    <div class="diagramsPanel">
      <div #paletteDiv class="paletteDiv"></div>
      <div #diagramDiv class="diagramDiv"></div>
      <div>
      <button (click)="onSave()">Save Changes</button>
      Diagram Model saved in JSON format:
      </div>
      <div>
      <textarea *ngIf="model" style="100%;height:300px">
    {{model.toJson()}}
    </textarea>
      </div>
    </div>

    二。下半部分显示json字符串:

    import { Component, OnInit, ViewChild, ElementRef, Input, Output, EventEmitter } from '@angular/core';
    import * as go from 'gojs';
    
    @Component({
      selector: 'app-diagram-detail',
      templateUrl: './diagram-detail.component.html',
      styleUrls: ['./diagram-detail.component.css']
    })
    export class DiagramDetailComponent implements OnInit {
      @Input() node: go.Node;
      @Input() data: any;
      constructor() { }
    
      ngOnInit() {
      }
      showDetails(node: go.Node | null) {
        this.node = node;
        if (node) {
          // copy the editable properties into a separate Object
          this.data = {
            text: node.data.text,
            color: node.data.color
          };
        } else {
          this.data = null;
        }
      }
    }

    diagram-detail.component.html

    <div *ngIf="node">
    <form *ngIf="node" #form="ngForm" (ngSubmit)="onCommitDetails()">
      Node Details:
      <div><label>Key: </label>{{node.key}}</div>
      <div><label>Text: </label><input [(ngModel)]="data.text" name="text"></div>
      <div><label>Color: </label><input [(ngModel)]="data.color" name="color"></div>
      <div><label>Location: </label>{{node.location.x.toFixed(2)}}, {{node.location.y.toFixed(2)}}</div>
      <div><label># Links: </label>{{node.linksConnected.count}}</div>
    </form>
    </div>

     三。与服务器通信,用了promise,可以实现异步传输,使用rxjs库需要具体说明路径,有部分冗余代码,不懂得可以看看angular官方文档http部分

    network.service.ts

    import { Injectable } from '@angular/core';
    import { Observable } from 'rxjs/Observable';
    import { HttpClient, HttpHeaders, HttpClientModule } from '@angular/common/http';
    import { of } from 'rxjs/observable/of';
    import { catchError, map, tap , retry } from 'rxjs/operators';
    import 'rxjs/add/operator/toPromise';
    import { MessageService } from './message.service';
    import {promise} from 'selenium-webdriver';
    const httpOptions = {
      //headers: new HttpHeaders({ 'Content-Type': 'application/json' })
      headers: new HttpHeaders({'Content-Type': 'application/x-www-form-urlencoded'})
    };
    @Injectable()
    export class NetworkService {
      public API = '//localhost:8888';
      private getModelUrl = this.API + '/gojs/get';  // URL to web api
      private saveModelUrl = this.API + '/gojs/save';
      constructor(private http: HttpClient,
                  private messageService: MessageService) { }
      // getModel(): Observable<string> {
      //   const url = `${this.getModelUrl}`;
      //   return this.http.get<string>(url).pipe(
      //    catchError(this.handleError<string>(`getModel`))
      //   );
      // }
    
      /** GET: get the model on the server */
      getModelText(): Promise<any> {
        // The Observable returned by get() is of type Observable<string>
        // because a text response was specified.
        // There's no need to pass a <string> type parameter to get().
        return this.http.get(this.getModelUrl).toPromise().catch(this.handleError());
      }
    
    
      /** PUT: update the model on the server */
      saveModel (data: string): Observable<any> {
        // return this.http.post(this.saveModelUrl, data, httpOptions).pipe(
        //   catchError(this.handleError<any>('saveModel'))
        // );
        const body = {model: data};
        this.http.post(this.saveModelUrl,
          'model=' + data, httpOptions).subscribe(model => {
          console.log(data);
        });
        return null;
      }
    
      /**
       * Handle Http operation that failed.
       * Let the app continue.
       * @param operation - name of the operation that failed
       * @param result - optional value to return as the observable result
       */
      private handleError<T> (operation = 'operation', result?: T) {
        return (error: any): Observable<T> => {
    
          // TODO: send the error to remote logging infrastructure
          console.error(error); // log to console instead
    
          // TODO: better job of transforming error for user consumption
          this.log(`${operation} failed: ${error.message}`);
    
          // Let the app keep running by returning an empty result.
          return of(result as T);
        };
      }
    
    
      /** Log a HeroService message with the MessageService */
      private log(message: string) {
        this.messageService.add('NetworkService: ' + message);
      }
    }

    message.service.ts没什么大用

    import { Injectable } from '@angular/core';
    
    @Injectable()
    export class MessageService {
      messages: string[] = [];
    
      add(message: string) {
        this.messages.push(message);
      }
    
      clear() {
        this.messages = [];
      }
    }

    服务器和angular位于不同端口,添加以下代码,否则不允许访问,这里用的服务器是springboot,服务器就比较简单了,不再细说

    import org.springframework.context.annotation.Configuration;  
    import org.springframework.web.servlet.config.annotation.CorsRegistry;  
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;  
    
    @Configuration  
    public class CorsConfig extends WebMvcConfigurerAdapter {  
    
        @Override  
        public void addCorsMappings(CorsRegistry registry) {  
            registry.addMapping("/**")  
                    .allowedOrigins("*")  
                    .allowCredentials(true)  
                    .allowedMethods("GET", "POST", "DELETE", "PUT")  
                    .maxAge(3600);  
        }  
    
    }  
  • 相关阅读:
    七天学会ASP.NET MVC(七)——创建单页应用
    七天学会ASP.NET MVC (二)——ASP.NET MVC 数据传递
    七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC
    七天学会ASP.NET MVC (四)——用户授权认证问题
    七天学会ASP.NET MVC (三)——ASP.Net MVC 数据处理
    网页倒计时跳转页面的效果
    javascript中最简单Ajax实例
    经典SQL语句大全(绝对的经典)
    .NET中的加密类(可设置密钥)
    非常强大的 jQuery.AsyncBox 弹窗插件
  • 原文地址:https://www.cnblogs.com/34fj/p/9252793.html
Copyright © 2011-2022 走看看