To update dictionary in Angular - angular8

export class AdduserComponent implements OnInit {
dict = {}
onsubmit(form:Form){
this.http.post(this.url, JSON.stringify(post_data)).subscribe( response => {
console.log(response);
if(response['Successful']){
this.dict["data"] = object.keys(response['successful'])[0]
this.router.navigate(['/users'])
}
}
}
Here, I have declared empty dict and want to update the dict after when I got response from api.

Your dict object will be updated from your code but if your are using into another component then you have to store either in localstorage or somewhere else in browser. Thank you :)

export class AdduserComponent implements OnInit {
dict = {}
onsubmit(form:Form){
let self = this
this.http.post(this.url, JSON.stringify(post_data)).subscribe( response => {
console.log(response);
if(response['Successful']){
self.dict["data"] = object.keys(response['successful'])[0]
this.router.navigate(['/users'])
}
}
}

Related

Vue 3 - Make the specific class properties reactive

Is there any possibility to make some properties of the class instance reactive?
In the MobX it's fairly easy to do:
class Doubler {
constructor(value) {
makeObservable(this, {
value: observable,
double: computed,
})
this.value = value
}
get double() {
return this.value * 2
}
}
But it looks like impossible to do it in Vue.
1.The most closest result that I get is the following result:
class Doubler {
constructor(value) {
this.value = ref(value)
this.double = computed(() => this.value.value * 2) // Ugly
}
}
The computed code is ugly and it's using also differs:
const doubler = new Doubler(1)
double.value = 2 // No way!
double.value.value = 2 // That's it! Ugly, but that's it.
2.I can pass the created object to reactive function, but it make all properties reactive and it doesn't affect the internal implementation and it still will be ugly.
Is there any way to reproduce MobX approach in Vue?
I don't think you can achieve it with classes. With objects though, the closest thing I can think of is something like this:
function createDoubler(value) {
const doubler = reactive({ value })
doubler.double = computed(() => state.value * 2)
return doubler
}
const doubler = createDoubler(4)
doubler.value // 4
doubler.value = 5
doubler.double // 10
EDIT: After giving it another thought I came up with the following solution:
class Doubler {
constructor(value) {
this._state = reactive({ value });
}
get value() {
return this._state.value;
}
set value(value) {
return this._state.value = value;
}
get double() {
return this._state.value * 2;
}
}
If you want to use ref instead of reactive:
class Doubler {
constructor(value) {
this._value = ref(value);
}
get value() {
return unref(this._value);
}
set value(value) {
return this._value = value;
}
get double() {
return this.value * 2;
}
}
Link to CodeSandbox

Angular 5 - Event emitter (Property 'update' does not exist on type ....)

I've got a component that I want to update when a person's name changes by emitting an event. My problem is the code doesn't compile because of an error. This is my code
ApplicationFormComponent
#Output() nameChange = new EventEmitter();
closeAccordion(isComplete: string, accordionToClose: string, accordion: NgbAccordion) {
if (accordionToClose === 'personal-details-panel') {
this.applicationStatusFlags.personalDetailsStatus = (isComplete === 'true');
this.nameChange.emit({ personId: this.personId });
}
}
ApplicationFormComponent.html
<name-display
[personId]="personId"
[placeHolderText]="'Hello'"
(nameChange)="update($event)">
</name-display>
NameDisplayComponent
import { Component, Input, OnChanges, SimpleChanges } from '#angular/core';
import { PersonService } from "../../../service/person.service";
#Component({
selector: 'name-display',
templateUrl: './NameDisplay.component.html',
providers: [PersonService]
})
export class NameDisplayComponent implements OnChanges {
constructor(private readonly personService: PersonService) { }
#Input() personId;
#Input() placeHolderText: string = "";
forename: string = "";
ngOnChanges(changes: SimpleChanges): void {
if (changes["personId"]) {
this.personService.getPersonDetails(this.personId).subscribe((res: IPersonDetails) => {
this.forename = res.forenames;
});
}
};
update(personId: number) {
alert("update name");
this.personService.getPersonDetails(personId).subscribe((res: IPersonDetails) => {
this.forename = res.forenames;
});
}
}
My problem is basically when I use angular cli with the command ng server --aot, it doesn't compile because of this error:
ERROR in src\app\component\ApplicationForm\ApplicationForm.component.html(42,9): : Property 'update' does not exist on type 'ApplicationFormComponent'.
I've written a similar component that uses an event emitter which doesn't have this problem, so I'm stuck with how to fix the error.
Any ideas?
It is because you are passing $event to method.
(nameChange)="update($event)"
But it accepts number.
update(personId: number) {
alert("update name");
}
Please change the method as below.
update(event:any) {
const personId = event as number
alert("update name");
}

ngx-chart error "TypeError: Object(...) is not a function"

I am trying to implements some statistics in my develepping platform and I try to use ngx-charts to display them. However I get an error and I can't figure out why.
I am using storedProcedures for MySQL statistics which I call from Java Restful Backend and return them in Angular 5 front-end. The returned table has the following two fields: Date and number of incidents per day. So the table returned by the backend has those two columns.
My code for the component rendering the chart is the following:
import {Component, OnInit} from '#angular/core';
import {StatisticsService} from '../../statistics.service';
class Data {
private _name: string;
private _value: number;
get name(): string {
return this._name;
}
set name(value: string) {
this._name = value;
}
get value(): number {
return this._value;
}
set value(value: number) {
this._value = value;
}
}
#Component({
selector: 'app-daily-incidents-statistics',
templateUrl: './daily-incidents-statistics.component.html',
styleUrls: ['./daily-incidents-statistics.component.css']
})
export class DailyIncidentsStatisticsComponent implements OnInit {
view: any[] = [700, 400];
data: any[] = [];
// options
showXAxis = true;
showYAxis = true;
gradient = false;
showLegend = false;
showXAxisLabel = true;
xAxisLabel = 'Ημέρα';
showYAxisLabel = true;
yAxisLabel = 'Αρ. Περιστατικών';
constructor(private statisticsService: StatisticsService) {
// Object.assign(this, { single })
// Object.assign(this, { data } );
}
colorScheme = {
domain: ['#5AA454', '#A10A28', '#C7B42C', '#AAAAAA']
};
onSelect(event) {
console.log(event);
}
async ngOnInit() {
console.log('NG ON INIT EXECUTION');
await this.getIncidentsByDay();
}
getIncidentsByDay() {
this.statisticsService.getIncidentsByDay()
.subscribe(
(results) => {
let temp = new Data();
for (let i in results) {
console.log(results[i][0] + '>>=====>> ' + results[i][1]);
temp.name = results[i][0];
temp.value = results[i][1];
this.data.push(temp);
}
const test = this.data;
// for (let i = 0; i < this.data.length; i++) {
// console.log('wtf: ' + this.data[i][0] + '::::' + this.data[i][1]);
// }
// console.log(results);
// console.log(JSON.stringify(results));
// Object.assign(this, {test});
}
);
}
}
However when I run the above code I get in JavaScript console the error:
ERROR TypeError: Object(...) is not a function
at BarVerticalComponent../src/common/base-chart.component.ts.BaseChartComponent.bindWindowResizeEvent (index.js:7818)
at BarVerticalComponent../src/common/base-chart.component.ts.BaseChartComponent.ngAfterViewInit (index.js:7730)
at callProviderLifecycles (core.js:12689)
at callElementProvidersLifecycles (core.js:12656)
at callLifecycleHooksChildrenFirst (core.js:12639)
at checkAndUpdateView (core.js:13794)
at callViewAction (core.js:14136)
at execComponentViewsAction (core.js:14068)
at checkAndUpdateView (core.js:13791)
at callViewAction (core.js:14136)
My Html Template File:
<div>
lalalal <br/>
ante pali... <br/>
kala ti na pw... <br/>
Gamiete pali... <br/>
<ngx-charts-bar-vertical
[view]="view"
[scheme]="colorScheme"
[results]="data"
[gradient]="gradient"
[xAxis]="showXAxis"
[yAxis]="showYAxis"
[legend]="showLegend"
[showXAxisLabel]="showXAxisLabel"
[showYAxisLabel]="showYAxisLabel"
[xAxisLabel]="xAxisLabel"
[yAxisLabel]="yAxisLabel"
(select)="onSelect($event)">
</ngx-charts-bar-vertical>
</div>
While the service for retreiving the values is:
import {Injectable} from '#angular/core';
import {HttpClient} from '#angular/common/http';
import {catchError} from 'rxjs/operators';
import {ErrorHandler} from '../shared/lib/error-handler';
import {Observable} from 'rxjs/Observable';
#Injectable()
export class StatisticsService {
constructor(private http: HttpClient) {
}
public getIncidentsByDay(): Observable<any> {
console.log("FEtching Incidents All By Day");
const url = 'statistics/incidents/day';
return this.http.get(url)
.pipe(catchError(ErrorHandler.handleError));
}
}
What am I doing wrong?
I am using Angular version 5.3 and ngx-charts 8.0 which is compatible with Angular 6 and not Angular 5. I installed ngx-charts version 7.4 and everything works fine.
I fixed the problem for me by downgrading to version 7.3.0
yarn add #swimlane/ngx-charts#7.3.0
I think I see the same with ngx-charts-bar-horizontal, whereas before this was not the case. The documentation page seems to be broken at the moment as well, so I assume the software has recently been updated in a broken way.
If you really need to use the 8.0 version, you can upgrade to angular 6 to solve the problem. Here is how you can do the upgrade from v5 to v6 https://stackoverflow.com/a/49474334
You can also think that the documention page is broken by now but ou can find it here https://swimlane.gitbook.io/ngx-charts/v/docs-test/installing

Declaring getter property when building SpyObj using jasmine.createSpyObj utility?

Let's say I have a class:
class MyRealClass {
get propOne() { return stuffFromTheServer; }
}
When testing, I want to achieve this functionality:
const mockClass = {
get propOne() { return someStuff; }
}
jasmine.spyOnProperty(mockClass, 'propOne', 'get');
By doing something like this...
const spy = jasmine.createSpyObj('mockClass', [
{methodName: 'propOne', accessType: 'get'}
]);
In other words, I want to build a SpyObj<MyRealClass> using the jasmine.createSpyObj and declare the getter properties as methods in the methodName array (the second parameter the the createSpyObj() method.
Is this possible?
createSpyObj takes an optional last parameter that lets you declare properties:
const spy = jasmine.createSpyObj(['here', 'be', 'methods'], { propOne: 'someStuff' });
or
const spy = jasmine.createSpyObj('mockClass', ['here', 'be', 'methods'], { propOne: 'someStuff' });
See here and here for the official docs
I did it surprisingly simple by this code:
const routerMock = jasmine.createSpyObj(['events']);
routerMock.events = of(new NavigationEnd(0, 'url1', 'url2'));
const serviceToTest = new SomeService(routerMock);

Call a Component method in Directive Angular 2

I have a directive which is supposed to call a method from component, but it fails doing this, what should be wrong ?
Here I will put the Directive, and a fragment of Component for understanding the problem..
Directive
import { Directive, EventEmitter, HostListener, Input, OnInit, Output } from '#angular/core';
import { GridComponent } from '../components/grid/grid.component';
import { Cell } from '../cell';
import { KEY_CODE } from '../keyCode.enum';
#Directive({
selector: '[appControl]',
})
export class GridDirective {
constructor(public gridComponent: GridComponent) {}
#HostListener('window:keydown', ['$event'])
handleKeyDown(event: KeyboardEvent) {
console.log(event.key);
const ITEMS = JSON.parse(localStorage.getItem('Grid'));
let key;
switch (event.key) {
case 'ArrowLeft': key = KEY_CODE.LEFT_ARROW;
break;
case 'ArrowUp': key = KEY_CODE.UP_ARROW;
break;
case 'ArrowRight': key = KEY_CODE.RIGHT_ARROW;
break;
case 'ArrowDown': key = KEY_CODE.DOWN_ARROW;
break;
}
this.gridComponent.move(ITEMS, key);
}
}
And here's the component method which it is supposed to call
move(array: Cell[][], key: KEY_CODE) {
localStorage.setItem('lastMove', JSON.stringify(key));
const DATA = this.gridService.move(array, this.score, key);
array = DATA.dataSheet;
this.score = DATA.rating;
this.best = this.gridService.scoreSender(this.score, this.best);
localStorage.setItem('Grid', JSON.stringify(array));
}
it's a wrong way to use a component as a service,
you should pass the "this" value from html and then assign it to gridComponent variable and for passing parameter to directive you can use input decorator
gridComponent :GridComponent;
#Input('appControl') set setGridComponent(gridComponent) {
this.gridComponent = gridComponent;
}
/// in html use property binding to pass the value to it
[appControl]="this"