Need help in creating network graph using visjs in angularjs - angularjs

I need help in making this plunker work something similar to this vis example in angularjs.
I am using <vis-network data="data" options="options"></vis-network> tag and below data and options
data
var nodes = [
{id: 1, label: 'Node 1'},
{id: 2, label: 'Node 2'},
{id: 3, label: 'Node 3'},
{id: 4, label: 'Node 4'},
{id: 5, label: 'Node 5'}
];
var edges = [
{from: 1, to: 3},
{from: 1, to: 2},
{from: 2, to: 4},
{from: 2, to: 5}
];
$scope.data = VisDataSet({
nodes: nodes,
edges: edges
});
options
$scope.options = {
autoResize: true,
height: '100%',
width: '100%'
};
There is no console error, what am I missing. Please help.

Your data is plain object, however nodes & edges should be an object of VisDataSet
var nodes = VisDataSet([
{id: 1, label: 'Node 1'},
{id: 2, label: 'Node 2'},
{id: 3, label: 'Node 3'},
{id: 4, label: 'Node 4'},
{id: 5, label: 'Node 5'}
]);
var edges = VisDataSet([
{from: 1, to: 3},
{from: 1, to: 2},
{from: 2, to: 4},
{from: 2, to: 5}
]);
$scope.data = {
nodes: nodes,
edges: edges
};
I have updated your plunker here.

Related

How to filter array object from another array object?

I want to make another array object from an array object, suppose I fetched a huge data from an api but I need only particular elements from that object. Exampl:-
const mainArray = [
{id: 1, name: 'John', age: 10},
{id: 2, name: 'Mark', age: 14},
{id: 3, name: 'Kevin', age: 15},
{id: 4, name: 'Julie', age: 16},
{id: 5, name: 'Liz', age: 10},
{id: 5, name: 'Emma', age: 11},
{id: 6, name: 'Robert', age: 13},
]
So suppose we have a huge list now I only want Kevin, Emma & Mark to display, for that I need an array of them like this:-
const specialKids = [
{id: 2, name: 'Mark', age: 14},
{id: 3, name: 'Kevin', age: 15},
{id: 5, name: 'Emma', age: 11},
]
How can I achieve that ?
To do this you can use the filter method of JS.
Documentation:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter?retiredLocale=de
in your case something like this should be enough:
let specialKids[];
specialKids = mainArray.filter(item => item.name === "Mark" || item.name === "Kevin" || item.name === "Emma")
ArrayList<String> yourintList = new ArrayList<>(Arrays.asList(yourArray));
for (int i = 0; i < yourintList.lenght; i++) {
if (yourintList.contains("Kevin")) {
do something
}

Map Angular Array to Object

I have been looking and have found a few good references for transforming arrays to objects, but I can't seem to find my use case. I have an array with the following format
[
{id: 1, name: 'hello', display: false},
{id: 5, name: 'hello2', display: true},
{id: 7, name: 'hello8', display: true},
]
and I would like to map it into something like this
{
5: {id: 5, name: 'hello2'},
7: {id: 7, name: 'hello8'}
}
I have been trying to use the map function, but I can't figure it out since I want the keys of my map to be an id. This is what I have so far but it is obviously wrong.
const myArray = [
{id: 1, name: 'hello', display: false},
{id: 5, name: 'hello2', display: true},
{id: 7, name: 'hello8', display: true},
];
const myMap = myArray.filter(row => row.display)
.map(row => {
return {row.id: {id: row.id, name: row.name}
});
Filter the array, map it to pairs of [id, obj], and convert to an object using Object.fromEntries(). You can use destructuring and rest syntax (...) to remove display.
Notes: if Object.fromEntries() is not supported, change target in TS Config to ES2019.
const arr = [{id: 1, name: 'hello', display: false},{id: 5, name: 'hello2', display: true}, {id: 7, name: 'hello8', display: true}]
const result = Object.fromEntries(
arr.filter(o => o.display)
.map(({ display, ...o }) => [o.id, o])
)
console.log(result)
Another option is to use Array.reduce() to create the object. In that case, you can skip objects with false display.
const arr = [{id: 1, name: 'hello', display: false},{id: 5, name: 'hello2', display: true}, {id: 7, name: 'hello8', display: true}]
const result = arr.reduce((acc, { display, ...o }) => {
if(display) acc[o.id] = [o.id, o]
return acc
}, {})
console.log(result)

vis.js Network regeneratorRuntime is not defined [regeneratorRuntime is not defined] error in Salesforce

Trying to use vis.js Network library in Salesforce I have tried both in LWC and in an Aura component with api version 40.0 but am receiving
regeneratorRuntime is not defined [regeneratorRuntime is not defined]
trying to use https://unpkg.com/browse/vis-network#8.1.0/standalone/umd/vis-network.min.js
Here is what I believe would solve your issue.
First Approach (only if library is small enough to be uploaded as LWC component)
You need to create two LWC component:
myNetwork
myNetwork.js
myNetwork.html
myNetwork.js-meta.xml
visNetworkLib
visNetwork.js = content of esm/vis-network.min.js
visNetwork.js-meta.xml
import { LightningElement } from 'lwc'
import { DataSet, Network } from 'c/visNetworkLib'
export default class MyNetwork extends LightningElement {
nodes = null
edgeds = null
renderedCallback () {
this.nodes = new DataSet([
{id: 1, label: 'Node 1'},
{id: 2, label: 'Node 2'},
{id: 3, label: 'Node 3'},
{id: 4, label: 'Node 4'},
{id: 5, label: 'Node 5'},
])
this.edges = new DataSet([
{from: 1, to: 3},
{from: 1, to: 2},
{from: 2, to: 4},
{from: 2, to: 5},
{from: 3, to: 3},
])
const container = this.template.querySelector('div.myNetwork')
this.network = new Network(container, {
nodes: this.nodes,
edges: this.edges,
}, {})
}
}
<template>
<div
lwc:dom="manual"
class="myNetwork"
></div>
</template>
Second approach
Create a static resource name visNetwork which is the uploaded vis-network.min.js
Then load it like that in myNetwork.js
import { LightningElement } from 'lwc'
import { ShowToastEvent } from 'lightning/platformShowToastEvent'
import visNetworkUrl from '#salesforce/resourceUrl/visNetwork'
import { loadScript } from 'lightning/platformResourceLoader'
export default class MyNetwork extends LightningElement {
nodes = null
edgeds = null
visLoaded = false;
renderedCallback() {
if (!this.visLoaded) {
this.visLoaded = true;
loadScript(this, visNetworkUrl).then(() => {
this.initializeNetwork();
})
.catch(error => {
this.dispatchEvent(
new ShowToastEvent({
title: 'Error loading vis network',
message: error.message,
variant: 'error'
})
);
});
}
}
initializeNetwork () {
this.nodes = new DataSet([
{id: 1, label: 'Node 1'},
{id: 2, label: 'Node 2'},
{id: 3, label: 'Node 3'},
{id: 4, label: 'Node 4'},
{id: 5, label: 'Node 5'},
])
this.edges = new DataSet([
{from: 1, to: 3},
{from: 1, to: 2},
{from: 2, to: 4},
{from: 2, to: 5},
{from: 3, to: 3},
])
const container = this.template.querySelector('div.myNetwork')
this.network = new Network(container, {
nodes: this.nodes,
edges: this.edges,
}, {})
}
}
I have figured it out, you have to load vis-data seperate from vis-network. you can find my working example here based on the NPSP Relationships and NPSP Affiliations.
https://github.com/mrainboldt/visNetworkMapLWC

Angular 2 declaring an array of objects

I have the following expression:
public mySentences:Array<string> = [
{id: 1, text: 'Sentence 1'},
{id: 2, text: 'Sentence 2'},
{id: 3, text: 'Sentence 3'},
{id: 4, text: 'Sentenc4 '},
];
which is not working because my array is not of type string rather contains a list of objects. How I can delcare my array to contain a list of objects?
*without a new component which declaring the a class for sentence which seem a waste
I assume you're using typescript.
To be extra cautious you can define your type as an array of objects that need to match certain interface:
type MyArrayType = Array<{id: number, text: string}>;
const arr: MyArrayType = [
{id: 1, text: 'Sentence 1'},
{id: 2, text: 'Sentence 2'},
{id: 3, text: 'Sentence 3'},
{id: 4, text: 'Sentenc4 '},
];
Or short syntax without defining a custom type:
const arr: Array<{id: number, text: string}> = [...];
public mySentences:Array<Object> = [
{id: 1, text: 'Sentence 1'},
{id: 2, text: 'Sentence 2'},
{id: 3, text: 'Sentence 3'},
{id: 4, text: 'Sentenc4 '},
];
Or rather,
export interface type{
id:number;
text:string;
}
public mySentences:type[] = [
{id: 1, text: 'Sentence 1'},
{id: 2, text: 'Sentence 2'},
{id: 3, text: 'Sentence 3'},
{id: 4, text: 'Sentenc4 '},
];
Another approach that is especially useful if you want to store data coming from an external API or a DB would be this:
Create a class that represent your data model
export class Data{
private id:number;
private text: string;
constructor(id,text) {
this.id = id;
this.text = text;
}
In your component class you create an empty array of type Data and populate this array whenever you get a response from API or whatever data source you are using
export class AppComponent {
private search_key: string;
private dataList: Data[] = [];
getWikiData() {
this.httpService.getDataFromAPI()
.subscribe(data => {
this.parseData(data);
});
}
parseData(jsonData: string) {
//considering you get your data in json arrays
for (let i = 0; i < jsonData[1].length; i++) {
const data = new WikiData(jsonData[1][i], jsonData[2][i]);
this.wikiData.push(data);
}
}
}
First, generate an Interface
Assuming you are using TypeScript & Angular CLI, you can generate one by using the following command
ng g interface car
After that set the data types of its properties
// car.interface.ts
export interface car {
id: number;
eco: boolean;
wheels: number;
name: string;
}
You can now import your interface in the class that you want.
import {car} from "app/interfaces/car.interface";
And update the collection/array of car objects by pushing items in the array.
this.car.push({
id: 12345,
eco: true,
wheels: 4,
name: 'Tesla Model S',
});
More on interfaces:
An interface is a TypeScript artifact, it is not part of ECMAScript. An interface is a way to define a contract on a function with respect to the arguments and their type. Along with functions, an interface can also be used with a Class as well to define custom types.
An interface is an abstract type, it does not contain any code as a class does. It only defines the 'signature' or shape of an API. During transpilation, an interface will not generate any code, it is only used by Typescript for type checking during development. - https://angular-2-training-book.rangle.io/handout/features/interfaces.html
public mySentences:Array<any> = [
{id: 1, text: 'Sentence 1'},
{id: 2, text: 'Sentence 2'},
{id: 3, text: 'Sentence 3'},
{id: 4, text: 'Sentenc4 '},
];
OR
public mySentences:Array<object> = [
{id: 1, text: 'Sentence 1'},
{id: 2, text: 'Sentence 2'},
{id: 3, text: 'Sentence 3'},
{id: 4, text: 'Sentenc4 '},
];
Datatype: array_name:datatype[]=[];
Example string: users:string[]=[];
For array of objects:
Objecttype: object_name:objecttype[]=[{}];
Example user: Users:user[]=[{}];
And if in some cases it's coming undefined in binding, make sure to initialize it on Oninit().
type NumberArray = Array<{id: number, text: string}>;
const arr: NumberArray = [
{id: 0, text: 'Number 0'},
{id: 1, text: 'Number 1'},
{id: 2, text: 'Number 2'},
{id: 3, text: 'Number 3 '},
{id: 4, text: 'Number 4 '},
{id: 5, text: 'Number 5 '},
];

KendoUI Grid - filter not showing

In my angular-kendo application I'm unable to get the Grid filter to show at all - not even a filter icon, just plain column headers.
Here is my html:
<div ng-controller="IntroductionWizardCtrl">
<h3 class="text-muted">Step 2: Select Application To Describe</h3>
<div kendo-grid id="grid"
k-data-source="dataSource"
k-sortable="true"
k-on-change="selectedItem = data"
k-selectable="'row'"
k-pageable='{ "refresh": true, "pageSizes": 5 }'
k-filterable="true">
</div>
<div>
<p>{{selectedItem}}</p>
</div>
<br/>
<input type="submit" class="btn btn-primary" wz-next value="Proceed to Next Step"
data-ng-click="" />
</div>
here is the corresponding Angular controller:
'use strict';
angular.module('wizardApp').controller('IntroductionWizardCtrl', ['$scope', '$location', '$rootScope',
function ($scope, $location, $rootScope) {
$scope.dataSource = {
data: [{id: 1, name: "Account Underwriting - Misc App", bu: 50},
{id: 2, name: "Achieve - Distributed", bu: 43},
{id: 3, name: "ACT!", bu: 27},
{id: 4, name: "Actuarial Database", bu: 29},
{id: 5, name: "Adjustment Invoicing System (AIS)", bu: 34},
{id: 6, name: "buncy Download", bu: 43},
{id: 7, name: "Ariba", bu: 27},
{id: 8, name: "Athena NY", bu: 29},
{id: 9, name: "Authoria", bu: 34},
{id: 10, name: "Avenue", bu: 43},
{id: 11, name: "BC&IT - Services", bu: 27},
{id: 12, name: "Billing Website", bu: 29},
{id: 13, name: "Blue Butler", bu: 34},
{id: 14, name: "BOE External", bu: 43},
{id: 15, name: "Builders Risk", bu: 27},
{id: 16, name: "Business Intelligence", bu: 29},
{id: 17, name: "Care Center", bu: 34}],
pageSize: 5, serverFiltering: true
};
$scope.rowSelected = function(e) {
var grid = e.sender;
var selectedRows = grid.select();
for (var i = 0; i < selectedRows.length; i++) {
$scope.selectedItem = grid.dataItem(selectedRows[i]);
break;
}
};
$scope.categoryDataSelectedRows=[];
$scope.categoryData=
{
data:
[{name: "General Application Information"},
{name: "User Interface configuration description"},
{name: "Application Architecture"},
{name: "Database"},
{ name: "Backup & DR"},
{name: "Design"},
{ name: "Operational data"},
{ name: "Testing"},
{name: "Application Configuration details"},
{ name: "Application connectivity requirements"},
{name: "Deployment Requirements"},
{name: "Application dependencies"},
{name: "Infrastructure dependencies"},
{ name: "Business value assessment"},
{ name: "Data requirements"},
{name: "Hosting OS requirements"},
{ name: "License requirements"}], pageSize: 5
}
$scope.rowSelectedCategory = function(e) {
var gridCategory = e.sender;
var selectedRowsCategory = gridCategory.select();
for (var i = 0; i < selectedRowsCategory.length; i++) {
$scope.selectedItemCategory = gridCategory.dataItem(selectedRowsCategory[i]);
break;
}
};
}
]);
I have looked over many examples, outside of Angular, where Kendo Grid has filtering working just fine. Yet, with angular-kendo I'm having this problem.
Well, as it turns out, my issue was with the order in which various css files were being loaded.
bootstrap was overwriting some other styles. Took me a while to sort this out, but now my angular-kendo grid is OK. Thanks for helping me!

Resources