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="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);
} }
Angular4中利用promise异步加载gojs的更多相关文章
- 简单的ListView中item图片异步加载
前言: 在android开发当中,从目标地址获取图片往往都是采用异步加载的方法.当完全加载完图片后在进行显示,也有些是直接将加载的图片一点一点的显示出来. 这两个区别只是对流的处理不同而已.现 ...
- Android中图片的异步加载
转: 1. 为什么要异步加载图片 下载图片比较费时,先显示文字部分,让加载图片的过程在后台,以提升用户体验 2. SoftReference的作用 栈内存—引用 堆内存—对象 Eg: Object ...
- Android新浪微博客户端(七)——ListView中的图片异步加载、缓存
原文出自:方杰|http://fangjie.info/?p=193转载请注明出处 最终效果演示:http://fangjie.sinaapp.com/?page_id=54 该项目代码已经放到git ...
- vue-awesome-swiper中的数据异步加载
<template> <div> //第一个轮播 加了v-if 判断,可以实现 loop 轮循 <swiper v-if="gglist.length>1 ...
- 小程序中使用ECharts 异步加载数据
官网例子都是同步的,怎么引入及同步demo请移步官网 <view class="container"> <ec-canvas id="mychart-d ...
- Vue中router路由异步加载组件-优化性能
何时使用异步加载组件 当首页app.js文件太大时,可以拆分组件异步加载,如果app.js文件很小时,不建议使用异步加载组件,因为异步加载组件时每次都要发送一个HTTP请求,这样的代价远比首页一次性加 ...
- WinForm中使用BackgroundWorker异步加载数据并使用进度条
在WinForm程序中,有时会因为加载大量数据导致UI界面假死,这种情况对于用户来说是非常不友好的.因此,在加载大量数据的情况下,首先应该将数据加载放在另一线程中进行,这样保证了UI界面的响应:其次可 ...
- 微信小程序中使用ECharts 异步加载数据 实现图表
<!--pages/bar/index.wxml--> <view class="container"> <ec-canvas id="my ...
- MVC4中EasyUI Tree异步加载JSON数据生成树
1,首先构造tree接受的格式化数据结构MODEL /// <summary> /// 定义EasyUI树的相关数据,方便控制器生成Json数据进行传递 /// </summar ...
随机推荐
- B树, B-树,B+树,和B*树的区别
B树: B树的搜索,从根结点开始,如果查询的关键字与结点的关键字相等,那么就命中: 否则,如果查询关键字比结点关键字小,就进入左儿子:如果比结点关键字大,就进入 右儿子:如果左儿子或右儿子的指针为空, ...
- Python中的import,from...import以及模块、包、库的概念
首先,说明一下,我使用的是python3.6.3win32版本,使用的IDE是pycharm2017社区免费版. 刚开始接触python编程不久,有很多概念都不是特别清楚,但是我觉得既然选择,尽自己最 ...
- DOM解析XML文件例子
DOM解析XML文件是一次性将目标文件中的所有节点都读入,然后再进行后续操作的方式. 一般分为以下几步: 1. 定义好目标XML文件路径path . 2. 实例化DOM解析工厂对象 ,Document ...
- 【html】html笔记综合
基本标签与属性 <html>全部 <body>主体 <h1>标题 <p>段落 <br>空行,一般都会额外添加,并不总是需要自己添加,可以在& ...
- Windows系统下MySQL解压版添加到系统服务
MySQL软件版本:64位 5.7.12 1.首先配置MySQL的环境变量,在系统环境变量Path的开头添加MySQL的bin目录的路径,以“;”结束,我的路径配置如下: 2.修改MySQL根目录下的 ...
- CFile与CArchive区别
一,区别 CFile是直接与磁盘打交道的一个文件对象,可以处理文本和二进制文件 CArchive将CFile作为自己的一个参数,通过该参数可以实现文本,二进制甚至继承至COject对象的类的本地存储和 ...
- 《锋利的jQuery》读书笔记(动画)
1.show()和hide() 实质就是改变当前DOM对象的display为block.none或inline-block(取决于之前的display),如下: $("element&quo ...
- 《Drools7.0.0.Final规则引擎教程》第3章 3.1 Hello World 实例
3.1 Hello World 实例 在上一章中介绍了Drools5x版本中规则引擎使用的实例,很明显在Drools7中KnowledgeBase类已经标注为"@Deprecated&quo ...
- mysql 视图,触发器,存储
一.视图 概念:其实就是一个临时表. 视图是一个虚拟表(非真实存在的),其本质是[根据SQL语句获取动态的数据库,并为其命名],用户使用时只需使用[名称]即可获取结果集.就可以当做表来使用. # 1. ...
- 转载(原标题:网站再遭新威胁 Struts2又曝高危漏洞啦)
自从著名J2EE框架Apache Struts2被曝出可被远程攻击者利用的执行漏洞后,关于Struts2的安全性便广受关注.近日,安全研究人员则再次发现了Struts2存在远程代码执行的漏洞,Stru ...