I can't get onCellValueChanged event called - ag-grid-angular

I'm testing ag-grid on angular 7. One of the things I want to do is detect cell changes in the grid, but I can't get the onCellValueChanged() fired. I'm just making my first steps in js and angular so maybe this is a silly question. Thanks
My grid definition in app.component.html:
<ag-grid-angular style="width: 950px; height: 320px;" class="ag-theme-balham"
[enableSorting]="true" [enableFilter]="true"
[rowData]="stocks" [columnDefs]="columnDefs" rowSelection="multiple"
[enterMovesDownAfterEdit]="true"
[enterMovesDown]="true">
(cellValueChanged)="onCellValueChanged($event)"
</ag-grid-angular>
My app.component.ts:
import { Component , OnInit} from '#angular/core';
import { StockService } from './stock.service';
import { stock } from './stock';
import {MatButtonModule, MatCheckboxModule} from '#angular/material';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'app';
stocks: stock[];
public loading = false;
pedidos: stock[];
constructor(private stockService: StockService) {this.stocks = []; }
columnDefs = [
{headerName: 'Código',
field: 'cod_ins',
width: 150,
suppressSizeToFit: true
},
{headerName: 'Cantidad',
field: 'pedido',
width: 110,
editable: true,
type: 'numericColumn',
}
];
onCellValueChanged(params: any) {
console.log('Estoy en onCellValueChanged !!!');
}
}

Uh, the problem was that the > was in the wrong place:
[enterMovesDown]="true">
(cellValueChanged)="onCellValueChanged($event)"
It should be here:
[enterMovesDown]="true"
(cellValueChanged)="onCellValueChanged($event)">
No error emitted by the compiler.

This happens because rowData is not changing (this.stocks = [] - alwasy, but it should be changed if you want detect it in onCellValueChanged() method)
Try to use:
#Input() stocks
or try to get stock from the server survey by polling

Related

Update embedded Swagger UI on toggle button change

I want to provide three different OpenApi definitions in a webapp, so users can read the documentation of different APIs.
The plan is to have a toggle button group with three buttons at the top and the swagger ui underneath it.
My problem is, that the swagger ui won't update if I click on a button. My approach looks like this:
api-docs.component.html
<mat-card>
<mat-button-toggle-group style="width: auto; display: flex;" (change)="toggleApiDoc($event)">
<mat-button-toggle checked value="mainPlattform" style="width: 100%">Main Plattform</mat-button-toggle>
<mat-button-toggle value="adapterHttp" style="width: 100%">Adapter HTTP</mat-button-toggle>
<mat-button-toggle value="adapterMqtt" style="width: 100%">Adapter MQTT</mat-button-toggle>
</mat-button-toggle-group>
<app-swagger-ui [url]=activeApiDoc></app-swagger-ui>
</mat-card>
api-docs.component.ts
import { Component } from '#angular/core';
import { MatButtonToggleChange } from '#angular/material/button-toggle';
import { environment } from 'src/environments/environment';
#Component({
selector: 'app-api-docs',
templateUrl: './api-docs.component.html',
styleUrls: ['./api-docs.component.scss']
})
export class ApiDocsComponent {
readonly mainApiDoc = environment.main_api_doc;
readonly httpAdapterApiDoc = environment.http_adapter_doc;
readonly mqttAdapterApiDoc = environment.http_adapter_doc;
activeApiDoc = this.mainApiDoc;
constructor() {
}
toggleApiDoc(event: MatButtonToggleChange) {
switch (event.value) {
case 'mainPlattform':
this.activeApiDoc = this.mainApiDoc;
break;
case 'adapterHttp':
this.activeApiDoc = this.httpAdapterApiDoc;
break;
case 'adapterMqtt':
this.activeApiDoc = this.mqttAdapterApiDoc;
break;
default:
this.activeApiDoc = this.mainApiDoc;
break;
}
}
}
swagger-ui.component.html
<div id="swagger"></div>
swagger-ui.component.ts
import { Component, Input, OnInit } from '#angular/core';
import SwaggerUI from 'swagger-ui';
#Component({
selector: 'app-swagger-ui',
templateUrl: './swagger-ui.component.html',
styleUrls: ['./swagger-ui.component.scss']
})
export class SwaggerUiComponent implements OnInit {
#Input() url: string = "";
constructor() { }
ngOnInit(): void {
const ui = SwaggerUI({
url: this.url,
dom_id: '#swagger'
});
}
}
environment.ts
export const environment = {
main_api_doc: 'https://petstore.swagger.io/v2/swagger.json',
http_adapter_doc: 'https://raw.githubusercontent.com/hjacobs/connexion-example/master/swagger.yaml'
};
As you can see I use random yaml files to test this. The first one gets rendered. I have an complete Swagger UI embedded in my webapp, but it won't render another Swagger UI, when I click a different toggle button. It just stays the same.
As you can tell, I'm not so good with typescript and angular. So I guess it shouldn't be too hard. But I can't tell whats wrong here.
The problem seems to be the angular lifecycle. When I tried to view all docs at the same time I saw that still only one would get rendered.
I changed the lifecycle hook function, where I create the Swagger UI and now it works.
import { Component, Input, OnChanges } from '#angular/core';
import SwaggerUI from 'swagger-ui';
#Component({
selector: 'app-swagger-ui',
templateUrl: './swagger-ui.component.html',
styleUrls: ['./swagger-ui.component.scss']
})
export class SwaggerUiComponent implements OnChanges {
#Input() url: string = "";
constructor() { }
ngOnChanges() {
const ui = SwaggerUI({
url: this.url,
dom_id: '#swagger'
});
}
}

Why is my Linechart not showing endpoint data?

I am building an angular web app that should display data from an endpoint . I have created the service class and I got chart.js installed but the graph is showing a blank linechart even though the console is displaying the data .
could it be a bug issue or am i doing something wrong ?
this is the component.ts class
import { Component, OnInit } from '#angular/core';
import {ApiService} from '../api.service';
import {Chart} from 'chart.js';
//import { map } from 'rxjs/operators';
#Component({
selector: 'app-transactions',
templateUrl: './transactions.component.html',
styleUrls: ['./transactions.component.scss']
})
export class TransactionsComponent implements OnInit {
Linechart;
data ;
market_price_usd ;
time_date ;
constructor(private apiService : ApiService) { }
ngOnInit() {
this.apiService.dailychart()
.subscribe((data: any) => {
this.data = data;
console.log(data);
this.market_price_usd = data.market_price_usd;
this.time_date = data.timestamp;
})
this.Linechart = new Chart ('canvas', {
type : 'line',
data : {
labels : this.time_date,
datasets :[
{
data : this.market_price_usd,
borderColor: '#3cb371',
backgroundColor: "#0000FF",
fill : false
},
]
},
options : {
legend: {
display: false
},
scales : {
xAxes: [{
display: true
}],
yAxes:[{
display: true
}],
}
}
});
};
}
this is the service class : could the issues be from the endpoint that I am consuming ?
mport { Injectable } from '#angular/core';
import {HttpClient, HttpHeaders} from '#angular/common/http';
import {Observable} from 'rxjs';
#Injectable({
providedIn: 'root'
})
export class ApiService {
constructor(private httpclient : HttpClient ) { }
public dailychart(){
return this.httpclient.get('https://api.blockchain.info/stats') as Observable <Array<any>>
}
}
This is the component.transaction.html code :
<div class="chart-container" style="position: relative; height:40vh; width:70vw">
<canvas id="canvas">{{ Linechart }}</canvas>
</div>
I can't add pictures right now but the chart displays but without data...Just random numbers showed in the Yaxis . This is the result of the endpoint on the console :
timestamp: 1580991534000
market_price_usd: 9669.3
hash_rate: 114554768282.53265
total_fees_btc: 2465817153
.......
Thanks in advance

Return plain JSON when calling specific router URL

I have an Angular application that shows different pages. I can navigate by (hamburger) menu or by calling the specific route (e.g. http://localhost/samplepage). Now I want to return plain JSON content when entering a specific route (e.g. http://localhost/myjson).
How can I manipulate the response so that it throws away all the Angular generated component code and instead return my plain JSON?
This seems to work:
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
name = 'Angular';
ngOnInit() {
const obj = {
name: 'Torsten',
age: 54
}
const thefile = new Blob([JSON.stringify(obj)], { type: "application/json" }) ;
let url = window.URL.createObjectURL(thefile);
window.location.href = url;
}
}
1. Solution
You can use json.stringify to show only plain json. Therefore you will still need a component, unless you want to have some guard methods to handle it there.
Like:
TS:
import { Component } from '#angular/core';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
getStringFromJson(): string {
JSON.stringify(this.someService.method())
}
}
HTML:
{{ getStringFromJson() }}
Stackblitz: https://stackblitz.com/edit/angular-yvamcm
2. Solution
Put a JSON file into your assets folder, which you edited before. Then use the Router service to redirect to this file in any time, but going to this file will cause, that you are not in the angular application anymore

Angular5 animated progress bar

I have started learning angular 5 two weeks ago and I want to practice on html event. Previously I used jquery for years so I need a little help.
What i want to do can be divided in two steps:
1) animate a progress bar from 0 to a n value between 0 and 100;
2) execute the method of point 1 when the progress bar appears on screen after scrolling.
I spent my morning searching a solution but I didn't find anything. Can someone help me?
Thanks
I suggest installing ngx-bootstrap and ngx-scroll-event via npm. Then play around with the settings and numbers until your liking. I'll provide what I got from just playing around with some of the stuff.
app.component.ts
import { Component } from '#angular/core';
import { ProgressbarConfig } from 'ngx-bootstrap/progressbar';
import { ScrollEvent } from 'ngx-scroll-event';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
providers: [{ provide: ProgressbarConfig, useFactory: getProgressbarConfig }]
})
export class AppComponent {
public max = 100;
public progress = 20;
public changeProgress(event: ScrollEvent, value: number, current: number): void {
this.progress = value;
}
}
export function getProgressbarConfig(): ProgressbarConfig {
return Object.assign(new ProgressbarConfig(), { animate: true, striped: true max: 100 });
}
app.componenet.html
<div style="height:1000px"></div>
<div style="height: 500px" detect-scroll (onScroll)="changeProgress($event, 70, progress)" [bottomOffset]="200" [topOffset]="200">
<div class="mb-2">
<progressbar class="progress-striped active" [value]="progress" [max]="100" type="success"> {{progress}} / {{max}}</progressbar>
</div>
</div>
app.module.ts
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { AppComponent } from './app.component';
import { ProgressbarModule } from 'ngx-bootstrap/progressbar';
import { ScrollEventModule } from 'ngx-scroll-event';
#NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
ScrollEventModule,
ProgressbarModule.forRoot()
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }

Angular 4 - service data is not persistent

I am having some trouble figuring out where I went wrong and would really appreciate some help with this.
I have a component: AudioComponent, which captures an html5 tag as a #ViewChild, then registers itself with a service: AudioService.
Here is the AudioComponent:
/* audio.component.ts */
import { Component, OnInit, Input, ViewChild } from '#angular/core';
import { IAudioOptions } from './audio-options';
export const defaultOptions: IAudioOptions = {
controls: true,
autoplay: false,
loop: false,
volume: 1.0,
startPosition: 0.0,
preload: "metadata",
muted: false
};
#Component({
selector: 'ng-audio',
templateUrl: './audio.component.html',
styleUrls: ['./audio.component.css']
})
export class AudioComponent implements OnInit {
#Input() src: any;
#Input() options: any = defaultOptions;
#Input() register: any;
#ViewChild('audio') player: any;
constructor() { }
ngOnInit() {
if (this.register) {
console.log("registering");
console.log(this.register(this));
}
}
play() {
this.player.nativeElement.play();
}
}
And the AudioService:
/* audio.service.ts */
import { Injectable } from '#angular/core';
import { AudioComponent } from './audio/audio.component';
#Injectable()
export class AudioService {
private players: AudioComponent[];
constructor() { }
register(player: AudioComponent) {
console.log("player registered");
if (this.players) {
this.players.push(player);
}
else {
console.log("initializing service");
this.players = [];
this.players.push(player);
}
return this.players;
}
getPlayers(): string[] {
var out: string[];
for (let i = 0; i < this.players.length; i++) {
out.push(this.players[i].src);
}
return out;
}
}
I'm instantiating two of the ng-audio components in my app.component.html file:
<!-- register refers to the AudioService.register function -->
<ng-audio [src]="src" [register]="register"></ng-audio>
<ng-audio [src]="src2" [register]="register"></ng-audio>
And the audio players themselves appear when I load the page.
What's puzzling is that I get the following logged to the console:
- registering
- player registered
- initializing service
- [AudioComponent]
- registering
- player registered
- initializing service // <- this should only happen the first time!
- [AudioComponent] // <- and this should now contain two elements!
For some reason, the players: AudioComponent[] property of the AudioService does not persist. So each time register() is called, it's like I'm calling it on a completely new AudioService instance!
Again, any help will be greatly appreciated. I'll be posting updates if I can figure this out.
EDIT: I've included my app.module.ts and app.component.ts files in case there's something I missed setting up the service as a provider.
AppModule:
/* app.module.ts */
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { AppComponent } from './app.component';
import { AudioComponent } from './audio/audio.component';
import { AudioService } from './audio.service';
#NgModule({
declarations: [
AppComponent,
AudioComponent
],
imports: [
BrowserModule
],
exports: [AudioComponent],
providers: [AudioService],
bootstrap: [AppComponent]
})
export class AppModule { }
And AppComponent:
/* app.component.ts */
import { Component } from '#angular/core';
import { AudioComponent } from './audio/audio.component';
import { AudioService } from './audio.service';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'app';
src = 'http://url.to/file.mp3';
src2 = 'http://url.to/another-file.mp3';
interval: any;
player: AudioComponent;
register: any;
play: any;
constructor(
private service: AudioService
) {
this.register = this.service.register;
this.play = this.service.getPlayers;
}
}