How to replace all the columns dynamically in Data Table using Angular2+? - javascript

My requirement to replace the all the columns when ever the changes/event is happening outside of the Data Table.
data table is displaying for the first time with selected columns(from event). if i select second one it's not displaying but columns in dtOptions getting changed but it's not displaying. I think clearing the view the problem but i tried using destroy it's not working out for me. some one please help me to achieve this.
HTML Code:
<div id="data-table-grid-slide">
<table datatable [dtOptions]="dtOptions" [dtTrigger]="dtTrigger" class="row-border hover"></table>
</div>
Angular Code for DataTable:
import {Component, ViewChild, OnInit, Input, AfterViewInit, OnDestroy, Output, EventEmitter} from '#angular/core';
import { DataTableDirective } from 'angular-datatables';
import { Subject } from 'rxjs';
import { ColumnObject } from '../data-tables-net/model/data-tables-model';
import { HttpClient } from '#angular/common/http';
import { DtServiceService} from '../data-tables-net/dt-service.service';
import { WindowRef} from '../services/WindowRef';
declare var $;
#Component({
selector: 'app-data-tables-net',
templateUrl: './data-tables-net.component.html',
styleUrls: ['./data-tables-net.component.css']
})
export class DataTablesNetComponent implements OnInit, AfterViewInit, OnDestroy {
#ViewChild('dataTable', {static: true}) table;
#ViewChild(DataTableDirective, {static: false}) dtElement: DataTableDirective;
dataTableColumn: Array<any> = [];
dtOptions: DataTables.Settings = {};
#Input() dataTableGrid: boolean;
#Input() tableShow: boolean;
#Output() tableShowChange = new EventEmitter<boolean>();
#Output() dataTableGridChange = new EventEmitter<boolean>();
dtTrigger: Subject<any> = new Subject();
// editor: any;
columnObject: ColumnObject = {
title: '',
data: ''
};
constructor(private http: HttpClient, private dtServiceService: DtServiceService, private winRef: WindowRef) { }
ngOnInit() {
this.dataTableGrid = true;
this.initDt();
}
ngAfterViewInit(): void {
// This method get called on pencil click of model in Data Model Visuvalizer
this.winRef.modelClick$.subscribe((modelObjAttributes) => {
this.dataTableGrid = true;
this.tableShow = false;
this.tableShowChange.emit(this.tableShow);
this.dataTableGridChange.emit(this.dataTableGrid);
console.log('modelObjAttributes', modelObjAttributes);
// tslint:disable-next-line: max-line-length
// this.dtOptions.columns = [{title: 'id', data: 'id'}, {title: 'name', data: 'name'}, {title: 'item code', data: 'item code'}, {title: 'addr', data: 'addr'}];
if (this.dtOptions.columns) {
// this.dtOptions.destroy = true;
// delete this.dtOptions.columns;
this.reRenderDataTable();
// console.log('columns', this.dtOptions.columns);
this.initDt();
this.dtOptions.columns = this.getModelDetails(modelObjAttributes);
// console.log(this.dtOptions.columns);
this.dtTrigger.next();
} else {
this.dtOptions.columns = this.getModelDetails(modelObjAttributes);
console.log(this.dtOptions.columns);
this.dtTrigger.next();
// this.dtOptions.destroy = true;
}
// delete this.dtOptions.columns;
});
}
initDt() {
this.dtOptions = {
// ajax: 'data/data.json',
// columns: [{title: 'Column1', data: 'column1'}],
paging: true,
searching: true,
ordering: true,
info: false,
responsive: true,
destroy: true
};
}
ngOnDestroy(): void {
// Do not forget to unsubscribe the event
this.dtTrigger.unsubscribe();
}
// This method used to get the details of model on clicking of pencil icon
getModelDetails(modelDetailsObj) {
return this.convertModelAttributesToDataTable(modelDetailsObj.options);
// this.getModelDetailsFromService(modelDetailsObj.id);
}
// This method is used to call the service to get the selected Models / Schema details from Database
getModelDetailsFromService(schemaId): void {
this.dtServiceService.getSelectedSchema(schemaId).subscribe(data => {
console.log(data);
},
error => {
console.log('Data is not getting');
});
}
// This method used to form the schema data for Data Table
convertModelAttributesToDataTable(attributesObject) {
this.dataTableColumn = [];
// delete this.dtOptions.columns;
for (const [index, obj] of attributesObject.entries()) {
if (obj) {
this.columnObject = { title: obj.text, data: obj.text};
console.log('columnObject', this.columnObject);
this.dataTableColumn.push(this.columnObject);
// console.log(this.dtOptions);
}
}
// this.dtTrigger.next();
return this.dataTableColumn;
}
// This method used re-render the data table with updated data's
reRenderDataTable(): void {
this.dtElement.dtInstance.then((dtInstance: DataTables.Api) => {
// Destroy the table first
// dtInstance.destroy();
// Call the dtTrigger to rerender again
this.dtTrigger.next();
});
}
}
I have created stackblitz for my requirement. In this example variables called columnsDataObj and dataUrl will change dynamically. it should get reflect in the data table. Please let me if you need more details:
https://stackblitz.com/edit/angular-datatables-gitter-4tavmk?file=app/app.component.ts

You need to also "destroy" dtOptions and the previous table from the template, also you have to make sure your template notices when the change is done, this are the main changes:
First destroy your previous DT completely, i added a flag called dtRendered:
dtRendered = true;
<table *ngIf="dtRendered" datatable [dtOptions]="dtOptions" class="row-border hover">
Also at your update method you have to make sure everything is destroyed and initialized again:
updateData() {
// destroy you current configuration
this.dtRendered = false
this.dtOptions = {
data: this.jsonData1.data,
columns: this.columnsDataObj1
};
// make sure your template notices it
this.cdr.detectChanges();
// initialize them again
this.dtRendered = true
this.cdr.detectChanges();
}
The this.cdr.detectChanges() call is needed so the lifecycle-hook notices about the change.
Here's your example working as expected:
https://stackblitz.com/edit/how-to-replace-all-the-columns-dynamically-in-data-table?file=app/app.component.ts

Related

How to make a select option as default selected in angular using ng-multiselect-dropdown?

So here I am getting data from the database and store it into events array. this events array data is shown on book-ticket.component.html using ng-multiselect-dropdown. From here on selecting one option this data corresponding to selected item stored in this.event.
I am passing id from the another component to this book-ticket.component and here we received it using
this.idByAllEvents = this.activatedRoute.snapshot.params.id;
HTML part of book-ticket Component is
<div class="form-group">
<label>Event</label>
<ng-multiselect-dropdown [placeholder]="'Select the Event'" [data]="this.events" name="event"
[(ngModel)]="this.event" [settings]="dropdownSettings1">
</ng-multiselect-dropdown>
</div>
.ts part of book-ticket component is
export class BookTicketComponent implements OnInit {
user:User;
event:Event;
offer:Offer;
// offer:string;
// event:string;
idByAllEvents: string; // This is coming from all events page
price:number;
percentageReduce:number;
offers:Offer[];
events:Event[];
dropdownSettings1: IDropdownSettings;
dropdownSettings2: IDropdownSettings;
selectedItem: any[];
constructor(private Userservice:UserService,private Offerservice:OfferService,
private Eventservice:EventService, private router:Router,
private activatedRoute:ActivatedRoute) {
this.idByAllEvents = this.activatedRoute.snapshot.params.id;
console.log(this.idByAllEvents);
this.user = new User();
// this.offer = new Offer();
// this.event = new Event();
// this.offer = new Offer();
// this.event = new Event();
this.selectedItem = [];
}
ngOnInit() {
this.dropdownSettings1 = {
singleSelection: true,
idField: '_id',
textField: 'name',
selectAllText: 'Select All',
unSelectAllText: 'UnSelect All',
itemsShowLimit: 3,
allowSearchFilter: true,
closeDropDownOnSelection: true,
};
this.Eventservice.GetEvents().subscribe(res => {
this.events = res;
this.justExecute();
this.Offerservice.GetOffers().subscribe(res => {
this.offers = res
})
});
justExecute(){
console.log(this.idByAllEvents);
console.log(this.events);
for (let index = 0; index < this.events.length; index++) {
const element = this.events[index]._id;
console.log(element);
if(element == this.idByAllEvents){
this.selectedItem.push(this.events[element]);
// this.selectedItem = this.events[element]
}
}
console.log(this.selectedItem);
}
}
SaveData(form:NgForm) {
if(form.valid) {...}
}
}
I want that option corresponding to this.idByAllEvents is selected by default ON HTML page. But dropdown list shows all the options of this.events.
I tried using setting selectedItem by function justExecute but console.log(this.selectedItem) gives undefined array.
If we get value corresponding to idByAllEvents in selectedItem then can we use [(ngModel)]="selectedItem" on html page to select that value.
How we should do this this.
Is any another way to do it present .
if ng-multiselect-dropdown is used in a reactive form's FormGroup, make sure you include [ngModelOptions]='{standalone: true}'

Angular DataTable not sorting asynchronous data

On a datatable that I am using, I am having mixed results when attempting to sort them by using the toggles in the table headers. It appears that columns that get populated by the response in my initial GET call populate and sort as expected. However, the columns with data that comes from the GET calls inside the outer subscription don't sort as expected. Ideally all columns would be able to sort properly.
When wrapping the this.dtTrigger.next() in a setTimeout() of 5000ms, all columns sorted as expected. So the question here is, how would I wait until the innermost GET call finishes to call the dtTrigger.next()so that all of the columns will be sortable once all of the data is finished loading in.
import { Component, OnInit, Input, OnChanges } from '#angular/core';
import { Subject } from 'rxjs';
import { BuildersService } from '#/services/builders/builders.service';
import { CommunitiesService } from '#/services/communities/communities.service';
import { ContactsService } from '#/services/contacts/contacts.service';
import { DataTableDirective } from 'angular-datatables';
#Component({
selector: 'datatable-builders',
templateUrl: './builder-datatable.component.html',
styleUrls: ['./builder-datatable.component.scss']
})
export class BuilderDatatableComponent implements OnInit {
#Input() title: string = '';
#Input() showFooter: boolean = true;
#Input() rowsPerPage: number = 10;
#Input() viewRoute: string = '';
#Input() viewText: string = 'View';
rows = [];
dtOptions: DataTables.Settings = {};
dtTrigger: Subject<any> = new Subject();
constructor(
private buildersService: BuildersService,
private communitiesService: CommunitiesService,
private contactsService: ContactsService
) { }
dataTablesInit() {
this.dtOptions = {
pagingType: 'simple_numbers',
lengthChange: false,
info: this.showFooter,
paging: this.showFooter,
columnDefs: [
{
targets: [4],
orderable: false,
searchable: false
}
],
initComplete: () => {
let searchLabels = document.querySelectorAll('.dataTables_filter > label');
searchLabels.forEach((label) => {
label.setAttribute('aria-label', 'Search/Filter Table');
});
}
};
}
ngOnInit() {
this.dataTablesInit();
// Get the table data
this.buildersService.getBuilders().subscribe((result: any) => {
// Get all Rows
let rows = result.body.map(row => {
let communities = [],
communitiesColumn = [],
managersColumn = [];
// Get the builders info and set up output
row.CommunityIDs.forEach((id) => {
this.communitiesService.getCommunity(id).subscribe((result: any) => {
communities.push(result.body);
communitiesColumn.push( result.body.Name );
});
});
row.Contacts.Managers.forEach((id) => {
this.contactsService.getContact(id).subscribe((result: any) => {
managersColumn.push(result.body);
});
});
console.log(row);
// Set additional row data
row.Communities = communities;
row.CommunitiesColumn = communitiesColumn;
row.ManagersColumn = managersColumn;
return row;
});
this.rows = result.body;
this.dtTrigger.next();
console.log(this.rows)
});
}
}
This is the synchronicity of JavaScript in general, you can use the keyword Async in the top level GET and Await keyword in the down level GET
e.g :
// Get the table data
async this.buildersService.getBuilders().subscribe((result: any) => {
...
//
// Get the builders info and set up output
row.CommunityIDs.forEach((id) => {
await this.communitiesService.getCommunity(id).subscribe((result: any) => {
...
//
communities.push(result.body);
communitiesColumn.push( result.body.Name );
});
});
row.Contacts.Managers.forEach((id) => {
this.contactsService.getContact(id).subscribe((result: any) => {
managersColumn.push(result.body);
});
});
console.log(row);
// Set additional row data
row.Communities = communities;
row.CommunitiesColumn = communitiesColumn;
row.ManagersColumn = managersColumn;
return row;
});
this.rows = result.body;
this.dtTrigger.next();
console.log(this.rows)
});
}
}

setColumnDefs does not work in Angular 5

As what has been suggested elsewhere,
setColumnDefs is not working for some ag-grids
How to initialize ag-grid api in angular2 application
I have already initialized the gridOptions in my class constructor. But when I tried to setColumnDefs, it still gave me error:
TypeError: Cannot read property 'setColumnDefs' of undefined
What else am I missing here?
export class ConfigurationComponent implements OnInit {
constructor(
private configurationService: ConfigurationService,
)
{
this.gridOptions = {
enableSorting: false,
rowData: this.tableData,
columnDefs: this.tableColumns,
onGridReady: () => {
this.gridOptions.api.sizeColumnsToFit();
this.gridOptions.api.setColumnDefs(this.tableColumns);
alert(this.gridOptions.api);
}
}
}
tableData: string[] = [];
tableList: string[] = [];
tableName: string;
tableColumns: [{headerName: string, field: string}] = [{headerName: "", field: ""}];
tableRecord: {};
gridOptions: GridOptions;
ngOnInit() {
this.retrieveTableList();
}
retrieveTableList(){
/*blah blah*/
}
retrieveTableData(){
/*blah blah*/
this.configurationService.retrieveTableData(this.schemaFullname, this.tableName).subscribe(data => {
/* GETTING tableColumn HERE from the service*/
this.gridOptions.api.setColumnDefs(this.tableColumns);
}, error => {
console.error(error);
this.alertService.error("Get table data error", "No table data retrieved from data source for " + this.tableName);
})
}
}
As your comment says,
It works now after I added [gridOptions]="gridOptions" in html.
Do you know why it worked?
As in your code, you are defining gridOptions in your constructor. In your onGridReady function, nobody knows from where api property (and sizeColumnsToFit, etc methods) gets added.
this.gridOptions = {
enableSorting: false,
rowData: this.tableData,
columnDefs: this.tableColumns,
onGridReady: () => {
this.gridOptions.api.sizeColumnsToFit();
this.gridOptions.api.setColumnDefs(this.tableColumns);
alert(this.gridOptions.api);
}
}
When you add [gridOptions]="gridOptions" in your component, ag-grid component uses the gridOptions object and injects other apis for you. Hence, it works afterwards.

How to add data dynamically to mat-table dataSource?

I have data streaming from backend and i see it printing in console now i am trying to push event to dataSource its throwing error dataSource is not defined. Can someone help how to dynamically add data to materialize table ?
stream.component.html
<mat-table #table [dataSource]="dataSource"></mat-table>
stream.component.ts
import {
Component,
OnInit
} from '#angular/core';
import {
StreamService
} from '../stream.service';
import {
MatTableDataSource
} from '#angular/material';
import * as io from 'socket.io-client';
#Component({
selector: 'app-stream',
templateUrl: './stream.component.html',
styleUrls: ['./stream.component.css']
})
export class StreamComponent implements OnInit {
displayedColumns = ['ticketNum', "assetID", "severity", "riskIndex", "riskValue", "ticketOpened", "lastModifiedDate", "eventType"];
dataSource: MatTableDataSource < Element[] > ;
socket = io();
constructor(private streamService: StreamService) {};
ngOnInit() {
this.streamService.getAllStream().subscribe(stream => {
this.dataSource = new MatTableDataSource(stream);
});
this.socket.on('newMessage', function(event) {
console.log('Datasource', event);
this.dataSource.MatTableDataSource.filteredData.push(event);
});
}
}
export interface Element {
ticketNum: number;
ticketOpened: number;
eventType: string;
riskIndex: string;
riskValue: number;
severity: string;
lastModifiedDate: number;
assetID: string;
}
I have found a solution for this problem, basically if you do:
this.dataSource.data.push(newElement); //Doesn't work
But if you replace the complete array then it works fine. So your final code must be :
this.socket.on('newMessage', function(event) {
const data = this.dataSource.data;
data.push(event);
this.dataSource.data = data;
});
You can see the issue here -> https://github.com/angular/material2/issues/8381
The following solution worked for me:
this.socket.on('newMessage', function(event) {
this.dataSource.data.push(event);
this.dataSource.data = this.dataSource.data.slice();
});
Another solution would be calling the _updateChangeSubscription() method for the MatTableDataSource object:
this.socket.on('newMessage', function(event) {
this.dataSource.data.push(event);
this.dataSource._updateChangeSubscription();
});
This method:
/**
Subscribe to changes that should trigger an update to the table's rendered rows. When the changes occur, process the current state of the filter, sort, and pagination along with the provided base data and send it to the table for rendering.
*/
Here is a very simple and easy solution:
displayedColumns = ['ticketNum', 'assetID', 'severity', 'riskIndex', 'riskValue', 'ticketOpened', 'lastModifiedDate', 'eventType'];
dataSource: any[] = [];
constructor() {
}
ngOnInit() {
}
onAdd() { //If you want to add a new row in the dataSource
let model = { 'ticketNum': 1, 'assetID': 2, 'severity': 3, 'riskIndex': 4, 'riskValue': 5, 'ticketOpened': true, 'lastModifiedDate': "2018-12-10", 'eventType': 'Add' }; //get the model from the form
this.dataSource.push(model); //add the new model object to the dataSource
this.dataSource = [...this.dataSource]; //refresh the dataSource
}
Hope this will help :)
from the docs
Since the table optimizes for performance, it will not automatically check for changes to the data array. Instead, when objects are added, removed, or moved on the data array, you can trigger an update to the table's rendered rows by calling its renderRows() method.
So, you can use ViewChild, and refreshRow()
#ViewChild('table', { static: true }) table;
add() {
this.dataSource.data.push(ELEMENT_DATA[this.index++]);
this.table.renderRows();
}
I put together an example in stackblitz
You could also use the ES6 spread operator or concat if you are not using ES6+ to assign the dataSource data to a new array.
In ES6+
this.socket.on('newMessage', function(event) {
this.dataSource.data = [...this.dataSource.data, event];
});
ECMAscript version 3+
this.socket.on('newMessage', function(event) {
this.dataSource.data = this.dataSource.data.concat(event);
});
I was stuck in same problem while creating select row and apply some action over rows data. This solution for your problem
imports..................
import { MatTableDataSource } from '#angular/material';
#component({ ...
export class StreamComponent implements OnInit {
// Initialise MatTableDataSource as empty
dataSource = new MatTableDataSource<Element[]>();
constructor() {}
...
// if you simply push data in dataSource then indexed 0 element remain undefined
// better way to do this as follows
this.dataSource.data = val as any;
// for your problem
ngOnInit() {
// ** important note .... I am giving solution assuming the subscription data is array of objects. Like in your case stream and in second event(parameter as callback)
this.streamService.getAllStream().subscribe(stream => {
// do it this way
this.dataSource.data = stream as any;
// note if you simply put it as 'this.dataSource.data = stream' then TS show you error as '[ts] Type 'string' is not assignable to type '{}[]''
});
this.socket.on('newMessage', (event) => {
console.log('Datasource', event);
// for this value
// this.dataSource.MatTableDataSource.filteredData.push(event); // I couldn't get what you are doing here
// SO try to explain what you are getting in this callback function val as event parameter ?????????????????
// but you can get it this ways
this.dataSource.filteredData = event as any;
});
}
Hope this will help you . If you have any question just ping me.
For me, nothing of these answers didn't work.
I had an observable that I subscribe to get new data.
the only solution that works for me was:
this.dataService.pointsNodesObservable.subscribe((data) => {
this.dataSource = new InsertionTableDataSource(this.paginator, this.sort, this.dataService);
this.dataSource.data = data;
});
render like a charm!
Insert the element at the beginning or any position you want then call the change subscription method of Mat Table dataSource. Here is the code.
this.dataSource.data.unshift(newItem);
this.dataSource._updateChangeSubscription();

How to reset injected object at view pop in Ionic2?

I'm trying to do the following:
I have an object like this:
let demo_obj = {
park_name: "Park #01",
assets:
[
{
id: 1,
name: "Test #01"
},
{
id: 2,
name: "Test #02"
},
{
id: 3,
name: "Test #03"
}
],
}
A page loops through the assets objects with an *ngFor listing each asset as a list item.
<ion-list>
<ion-item *ngFor="let asset of demo_obj.assets" (click)="gotoAsset(asset)">
<ion-avatar item-left>
<img [src]="asset.cover_image_public_path">
</ion-avatar>
<h2>{{asset.nome}}</h2>
</ion-item>
</ion-list>
When the user clicks the button the following code gets executed:
gotoAsset(asset) {
this.navCtrl.push(AssetPage, { asset: asset });
}
This pushes a page displaying the asset details.
When the new page gets on the stack it fetches the asset from the nav params and it makes a backup copy of it stringifying it.
ngOnInit() {
this.asset = this.navParams.get("asset");
this.original_asset = JSON.stringify(this.asset);
}
The user here, can change several properties on the asset. But when he tries to go back without saving changes the app asks the user with a confirmation alert if he is sure to exit loosing changes:
ionViewCanLeave(): boolean {
if (JSON.stringify(this.asset) === this.original_asset) {
return true;
}
if (this.can_go_back) {
return true;
}
this.askForLeaveConfirmation();
return false;
}
private askForLeaveConfirmation() {
let confirm = this.alertCtrl.create({
title: 'Do you confirm?',
message: 'Leaving the page without saving, will reset the resource at its original state. Are you sure?',
buttons: [
{
text: 'Disagree',
handler: () => {
console.log('Disagree clicked');
}
},
{
text: 'Agree',
handler: () => {
this.asset = JSON.parse(this.original_asset);
this.can_go_back = true;
this.navCtrl.pop();
console.log('Agree clicked');
}
}
]
});
confirm.present();
}
At this point if he chooses Agree, the resource gets reseted. All works fine, in fact you can see in a small fraction of time the resource getting reseted before the animation start.
The weird thing happens when the this.navCtrl.pop() gets called. The previous page keeps the changes even if the resource were reseted.
I thought that it's in some way linked with the previous page since I'm continuously passing the same object between the pages. Where am I doing wrong?
I've managed to solve it with a workaround.
Creating a service called SyncService, which will take care to backup the given object and provides a copy of it.
Then that copy can be fetched back with the proper method.
Keeping a backed up copy of the object allows me to perform a check on the ionViewCanLeave() method and on the constructor of the parent page.
The core key was using Events. When the user confirms the reset of the object in the alert, an event is published, and the constructor of the parent page subscribes at that event.
Inside the subscription, we'll loop all the current assets searching for the same ID, then if found the entire object gets overwritten.
SyncService class:
import { Injectable } from "#angular/core";
#Injectable()
export class SyncService {
public resource;
public workOnCopy(resource: any, res_type: string): boolean {
sessionStorage.setItem("astrid_mobile_tmp_" + res_type + "_bak", JSON.stringify(resource));
this.resource = resource;
return this.resource;
}
public getBackedUpResource(res_type: string, parse: boolean = true): any {
let res = sessionStorage.getItem("astrid_mobile_tmp_" + res_type + "_bak");
if (!res) {
return false;
}
if (parse) {
JSON.parse(res);
}
return res;
}
}
The child page (AssetPage):
#Component({
selector: 'page-asset',
templateUrl: 'asset.html'
})
export class AssetPage implements OnInit {
public asset;
private can_go_back: boolean = false;
constructor(
private navCtrl: NavController,
private navParams: NavParams,
private alertCtrl: AlertController,
private Events: Events,
private SyncService: SyncService,
) {
this.asset = this.SyncService.workOnCopy(this.navParams.get("asset"), "asset");
}
ionViewCanLeave(): boolean {
if (JSON.stringify(this.asset) === this.SyncService.getBackedUpResource("asset")) {
return true;
}
if (this.can_go_back) {
return true;
}
this.askForLeaveConfirmation();
return false;
}
private askForLeaveConfirmation() {
let confirm = this.alertCtrl.create({
title: 'Do you confirm?',
message: 'Leaving the page without saving, will reset the resource at its original state. Are you sure?',
buttons: [
{
text: 'Disagree',
handler: () => {
console.log('Disagree clicked');
}
},
{
text: 'Agree',
handler: () => {
console.log("Event fired");
this.Events.publish("asset:reseted", this.SyncService.getBackedUpResource("asset"));
this.can_go_back = true;
this.navCtrl.pop();
console.log('Agree clicked');
}
}
]
});
confirm.present();
}
}
The parent page (ParkPage) constructor:
constructor(
private navCtrl: NavController,
private navParams: NavParams,
private Events: Events,
) {
this.park = this.navParams.get("park");
this.Events.subscribe("asset:reseted", (bak_asset) => {
let asset = JSON.parse(bak_asset);
for (let i = 0; i < this.park.assets.length; i++) {
if (this.park.assets[i].id == asset.id) {
this.park.assets[i] = asset;
}
}
});
}

Categories

Resources