Angular4中利用promise异步加载gojs

Stella981
• 阅读 755

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

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

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

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

Angular4中利用promise异步加载gojs

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

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="width: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);  
    }  

}
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Easter79 Easter79
3年前
swap空间的增减方法
(1)增大swap空间去激活swap交换区:swapoff v /dev/vg00/lvswap扩展交换lv:lvextend L 10G /dev/vg00/lvswap重新生成swap交换区:mkswap /dev/vg00/lvswap激活新生成的交换区:swapon v /dev/vg00/lvswap
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
ES6 新增的数组的方法
给定一个数组letlist\//wu:武力zhi:智力{id:1,name:'张飞',wu:97,zhi:10},{id:2,name:'诸葛亮',wu:55,zhi:99},{id:3,name:'赵云',wu:97,zhi:66},{id:4,na
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这