Angular 4 - update list after delete - ruby-on-rails

I am building a site for upcoming concert events. When I create a new event I got it to save to the backend (Ruby on Rails) and immediately display the new event in the event list. However, when I delete an event, the event gets deleted in the database but the front end does not refresh.
event-create.component.ts
import { Component, OnDestroy, OnInit } from '#angular/core';
import { FormControl, FormGroup, Validators, FormBuilder } from "#angular/forms";
import { EventService } from "../event.service";
import { Event } from "../event";
import { Venue } from "../../venue/venue";
import { VenueService } from "../../venue/venue.service";
import { ActivatedRoute, Router} from '#angular/router';
import { BsDatepickerConfig } from 'ngx-bootstrap/datepicker'
import { DataService } from '../../data.service';
#Component({
selector: 'app-event-create',
templateUrl: './event-create.component.html',
styleUrls: ['./event-create.component.scss']
})
export class EventCreateComponent implements OnInit {
id: number;
event: Event;
venues: Venue[];
bsValue: Date = new Date();
date: string;
time: string;
datepickerModel: Date = new Date();
bsConfig: Partial<BsDatepickerConfig>;
eventTime: Date = new Date(this.bsValue.getFullYear(), this.bsValue.getMonth(), this.bsValue.getDay(), 19, 0, 0, 0);
mstep: number = 15;
eventForm: FormGroup;
constructor(private route: ActivatedRoute,
private router: Router,
private eventService: EventService,
private venueService: VenueService,
private data: DataService,
fb: FormBuilder) {
this.eventForm = fb.group({
'title': [null, Validators.required],
'venue': [1, Validators.required],
'date': null,
'time': null,
'description': [null, Validators.required]
});
this.bsConfig = Object.assign({}, { containerClass: 'theme-red' });
}
ngOnInit(): void {
this.getVenues();
}
getVenues(){
this.venueService.query().subscribe(
venues => {
this.venues = venues;
},
err => {
console.log(err);
}
);
}
onSubmit() {
Object.keys(this.eventForm.controls).forEach(field => {
const control = this.eventForm.get(field);
control.markAsTouched({ onlySelf: true });
});
if (this.eventForm.valid) {
let date: Date = new Date(this.eventForm.controls['date'].value);
let time: Date = new Date(this.eventForm.controls['time'].value);
let event: Event = new Event(
null,
this.eventForm.controls['venue'].value,
this.formatTimestamp(date, time),
this.eventForm.controls['title'].value,
this.eventForm.controls['description'].value
);
this.eventService.save(event).subscribe();
this.data.addEvent(event);
this.router.navigate(['/event']);
}
}
formatTimestamp(date: Date, time: Date): number {
let timezoneOffset: number = time.getTimezoneOffset() / 60;
if((time.getHours() + timezoneOffset) > 23){
date.setDate(date.getDate() + 1);
}
date.setUTCHours(time.getUTCHours());
date.setUTCMinutes(time.getMinutes());
date.setUTCSeconds(time.getSeconds());
return date.getTime();
}
redirectUserPage() {
this.router.navigate(['/user']);
}
}
event-index.component.ts
import { Component, OnInit } from '#angular/core';
import { Event } from '../event';
import { EventService } from '../event.service';
import { Router } from '#angular/router';
import { DataService } from '../../data.service';
import { Output, EventEmitter } from '#angular/core';
#Component({
selector: 'app-event-index',
templateUrl: './event-index.component.html',
styleUrls: ['./event-index.component.scss']
})
export class EventIndexComponent implements OnInit {
#Output()
someEvent = new EventEmitter();
event: Event;
private events: Event[];
constructor(
private router: Router,
private eventService: EventService,
private data: DataService
) { }
ngOnInit() {
this.getEvents();
this.data.currentEvent.subscribe(event => this.event = event);
}
getEvents(){
this.eventService.query().subscribe(
events => {
this.events = events;
},
err => {
console.log(err);
}
)
}
newEvent(){
this.router.navigate(['/event/create']);
}
editEvent(event: Event){
if(event){
this.router.navigate(['/event/edit', event]);
}
}
deleteEvent(event: Event){
let index = this.events.indexOf(event);
if(index > -1){
this.eventService.delete(event).subscribe(
event => {
this.events.slice(index, 1);
}
);
}
}
}
data.service.ts
import { Injectable } from '#angular/core';
import { Subject } from 'rxjs/Subject';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Event } from './event/event';
#Injectable()
export class DataService{
currentEvent: BehaviorSubject<Event> = new BehaviorSubject<Event>(null);
public addEvent(newEvent: Event): void{
this.currentEvent.next(newEvent);
}
}
event-create.component.html
<div class="row justify-content-center">
<h1>New Event</h1>
</div>
<div class='row justify-content-center'>
<div class='col-6'>
<form [formGroup]='eventForm' (ngSubmit)="onSubmit(eventForm.value)">
<div class='form-group'>
<label>Title</label>
<input type="text" class='form-control' [ngClass]="{'is-invalid': eventForm.controls['title'].invalid && eventForm.controls['title'].touched}" formControlName="title">
<div *ngIf="eventForm.controls['title'].hasError('required')" class="invalid-feedback">Title is required</div>
</div>
<div class='form-group'>
<label>Description</label>
<textarea formControlName="description" class='form-control' [ngClass]="{'is-invalid': eventForm.controls['description'].invalid && eventForm.controls['description'].touched}"></textarea>
<div *ngIf="eventForm.controls['description'].hasError('required')" class="invalid-feedback">Description is required</div>
</div>
<div class='form-group'>
<label>Venue</label>
<select class='form-control' formControlName='venue'>
<option *ngFor="let venue of venues" [value]="venue.id">{{venue.name}}</option>
</select>
</div>
<div class="form-group">
<label>Date</label>
<input type="text" class="form-control" bsDatepicker [bsConfig]="bsConfig" [(ngModel)]="datepickerModel" formControlName='date'>
</div>
<div class='form-group'>
<label>Time</label>
<timepicker [(ngModel)]="eventTime" [minuteStep]="mstep" formControlName='time'></timepicker>
</div>
<button type="submit" class='btn btn-default'>Submit</button>
<pre>{{eventForm.value | json}}</pre>
</form>
</div>
</div>
event.service.ts
import { Injectable } from '#angular/core';
import { Event } from './event';
import { HttpClient } from '#angular/common/http';
import { Response } from '#angular/http';
import { Observable } from 'rxjs/Observable'
#Injectable()
export class EventService {
private apiUrl = 'http://localhost:3000/events';
constructor(private http: HttpClient) {}
query(): Observable<any>{
return this.http.get(this.apiUrl);
}
get(id: number): Observable<Event>{
return null;
}
save(event: Event): Observable<any>{
return this.http.post(this.apiUrl, event);
}
delete(event: Event): Observable<any>{
console.log(event);
return this.http.delete(this.apiUrl + '/' + event.id)
}
update(event: Event): Observable<Event>{
return null;
}
}

You are using slice() where you should be using splice() in deleteEvent()
Try changing:
this.events.slice(index, 1);
To
this.events.splice(index, 1);

Related

Angular 6 Async Binding Crazy Behavior

I am using a material dialog to display details of entries. I pass data to dialogue in constructor. However despite the fact that variable exists, and is not null, data is not displayed for some reason.
Bellow is my Dialogue.ts
import {Component, Inject, OnDestroy, OnInit} from '#angular/core';
import {Incident} from '../incident';
import {IncidentsService} from '../incidents.service';
import {MAT_DIALOG_DATA} from '#angular/material';
import {Subscription} from 'rxjs';
#Component({
selector: 'app-incident-details',
templateUrl: './incident-details.component.html',
styleUrls: ['./incident-details.component.css']
})
export class IncidentDetailsComponent implements OnInit, OnDestroy {
public incident: Incident;
private subscription: Subscription;
constructor(#Inject(MAT_DIALOG_DATA) public data: any, private incidentsService: IncidentsService) {
this.incident = this.data.incident;
console.log('?????????? ' + JSON.stringify(this.incident));
}
renderPDF(id: number) {
this.subscription = this.incidentsService.getPdfById(id)
.subscribe(response => {
// console.log('Response: ' + response);
const file = new Blob([response], {type: 'application/pdf'});
const fileURL = URL.createObjectURL(file);
// this.dialogRef.close();
window.open(fileURL);
});
}
ngOnInit() {
}
ngOnDestroy(): void {
if (this.subscription) {
this.subscription.unsubscribe();
}
}
}
Bellow is the template dialogue.html
<mat-card>
<h2 mat-dialog-title style="text-align: center; text-decoration: underline;"><b>Έκθεση Ιστολογικής Εξέτασης</b></h2>
<br/>
<mat-dialog-content>
<div>{{incident|json}}</div> **// Printing Incident Data**
<table>
<tr>
<td><b>Αρ. Πρωτοκόλλου: </b>{{incident.protocolNo}} </td>
<td><b>Ημερομηνία Παραλαβής: </b>{{incident.dateIN | date:'dd-MM-yyyy'}} </td>
</tr>
<tr>
<td><b>Ονοματεπώνυμο: </b> {{incident.patient?.lastName.toString()}} {{incident.patient?.firstName}} </td>
<td><b>Ημ. Γέννησης: </b> {{incident.patient?.birthday | date:'dd-MM-yyyy'}} </td>
</tr>
</table>
<p><b>Αποστέλων Ιατρός: </b> {{incident.doctor?.lastName}} {{incident.doctor?.firstName}}</p>
<div *ngIf="incident.klinikesPlirofories">
<h3 class="subSection" mat-dialog-title>Κλινικές Πληροφορίες</h3>
<p>{{incident.klinikesPlirofories}}</p>
</div>
<div *ngIf="incident.yliko">
<h3 class="subSection" mat-dialog-title>Υλικό</h3>
<p>{{incident?.yliko}}</p>
</div>
<div *ngIf="incident.makro">
<h3 class="subSection" mat-dialog-title>Μακροσκοπικά</h3>
<p>{{incident?.makro}}</p>
</div>
<div *ngIf="incident.mikro">
<h3 class="subSection" mat-dialog-title>Μικροσκοπικά</h3>
<p>{{incident?.mikro}}</p>
</div>
<div *ngIf="incident.anoso">
<h3 class="subSection" mat-dialog-title>Ανοσοϊστοχημικός Έλεγχος</h3>
<p>{{incident.anoso}}</p>
</div>
<div *ngIf="incident.anosoEkthesi">
<h3 class="subSection" mat-dialog-title>Ανοσο Έκθεση</h3>
<p>{{incident.anosoEkthesi}}</p>
</div>
<div *ngIf="incident.histo">
<h3 class="subSection" mat-dialog-title>Iστοχημικός Έλεγχος</h3>
<p>{{incident.histo}}</p>
</div>
<div *ngIf="incident.symperasma">
<h3 class="subSection" mat-dialog-title>Συμπέρασμα</h3>
<p>{{incident?.symperasma}}</p>
</div>
<div *ngIf="incident.mikroskopikaSymperasma">
<h3 class="subSection" mat-dialog-title>Μικροσκοπικά Συμπέρασμα</h3>
<p>{{incident?.mikroskopikaSymperasma}}</p>
</div>
<div>
<h3 class="subSection" mat-dialog-title>Πληρωμή</h3>
<p>{{incident.isPayed ? 'Ναι' : 'Όχι'}}</p>
</div>
<div>
<h3 class="subSection" mat-dialog-title>Καρκίνος</h3>
<p>{{incident.cancer ? 'Θετικό' : 'Αρνητικό'}}</p>
</div>
<div *ngIf="incident.signingDoctor">
<h3 class="subSection" mat-dialog-title>Υπογράφων Ιατρός</h3>
<p>{{incident.signingDoctor?.lastName}} {{incident.signingDoctor?.firstName}}</p>
</div>
<div *ngIf="incident.simpliromatikiEkthesi">
<h3 class="subSection" mat-dialog-title>Συμπληρωματική Έκθεση</h3>
<p>{{incident?.simpliromatikiEkthesi}}</p>
</div>
</mat-dialog-content>
</mat-card>
<!--<div>{{incident|json}}</div>-->
<mat-dialog-actions>
<button mat-raised-button mat-dialog-close color="warn">Close</button>
<button mat-raised-button color="primary" (click)="renderPDF(incident.id)">
<i class="material-icons">print</i>
</button>
</mat-dialog-actions>
And bellow there is a screenshot:
As you can see incident get printed and exists with data both in console and in template. However everywhere else in template, by calling incident.member prints nothing.
I am opening dialogue and passing data to it using the function below from another component.
async openDialog(id: number) {
let incident: Incident;
this.subscriptions.push(
await this.incidentsService.getIncidentByID(id).subscribe(response => {
incident = response;
const dialogRef = this.dialog.open(IncidentDetailsComponent, {height: '900px', width: '900px', 'data': {'incident': response}});
}));
// const dialogRef = this.dialog.open(IncidentDetailsComponent, {height: '900px', width: '900px', 'data': {'incident': incident}});
}
Bellow is getIncidentByID() function
getIncidentByID(id: number): Observable<Incident> {
const incidentUrl = 'incidents/details/' + id;
return this.http.get<Incident>(incidentUrl)
.pipe(catchError(ErrorHandler.handleError));
}
Bellow is Incident.ts
import {Patient} from '../patients/patient';
import {Clinic} from '../clinics/clinic';
import {Doctor} from 'app/doctors/doctor';
import {SigningDoctor} from '../signing-doctors/signing-doctor';
import {BodyPart} from '../body-part/BodyPart';
export class Incident {
private _id: number;
private _protocolNo: string;
private _dateIN: any;
private _dateOUT: any;
private _isPayed: boolean;
private _yliko: string;
private _makro: string;
private _anoso: string;
private _mikro: string;
private _symperasma: string;
private _patient: Patient;
private _clinic: Clinic;
private _doctor: Doctor;
private _histo: string;
private _klinikesPlirofories: string;
private _simpliromatikiEkthesi: string;
private _signingDoctor: SigningDoctor;
private _mikroskopikaSymperasma: string;
private _cancer: boolean;
private _anosoEkthesi: string;
private _bodyPart: BodyPart;
get id(): number {
return this._id;
}
set id(value: number) {
this._id = value;
}
get protocolNo(): string {
return this._protocolNo;
}
set protocolNo(value: string) {
this._protocolNo = value;
}
get dateIN(): any {
return this._dateIN;
}
set dateIN(value: any) {
this._dateIN = value;
}
get dateOUT(): any {
return this._dateOUT;
}
set dateOUT(value: any) {
this._dateOUT = value;
}
get isPayed(): boolean {
return this._isPayed;
}
set isPayed(value: boolean) {
this._isPayed = value;
}
get yliko(): string {
return this._yliko;
}
set yliko(value: string) {
this._yliko = value;
}
get makro(): string {
return this._makro;
}
set makro(value: string) {
this._makro = value;
}
get anoso(): string {
return this._anoso;
}
set anoso(value: string) {
this._anoso = value;
}
get mikro(): string {
return this._mikro;
}
set mikro(value: string) {
this._mikro = value;
}
get symperasma(): string {
return this._symperasma;
}
set symperasma(value: string) {
this._symperasma = value;
}
get mikroskopikaSymperasma(): string {
return this._mikroskopikaSymperasma;
}
set mikroskopikaSymperasma(value: string) {
this._mikroskopikaSymperasma = value;
}
get patient(): Patient {
return this._patient;
}
set patient(value: Patient) {
this._patient = value;
}
get clinic(): Clinic {
return this._clinic;
}
set clinic(value: Clinic) {
this._clinic = value;
}
get doctor(): Doctor {
return this._doctor;
}
set doctor(value: Doctor) {
this._doctor = value;
}
get histo(): string {
return this._histo;
}
set histo(value: string) {
this._histo = value;
}
get klinikesPlirofories(): string {
return this._klinikesPlirofories;
}
set klinikesPlirofories(value: string) {
this._klinikesPlirofories = value;
}
get simpliromatikiEkthesi(): string {
return this._simpliromatikiEkthesi;
}
set simpliromatikiEkthesi(value: string) {
this._simpliromatikiEkthesi = value;
}
get signingDoctor(): SigningDoctor {
return this._signingDoctor;
}
set signingDoctor(value: SigningDoctor) {
this._signingDoctor = value;
}
get cancer(): boolean {
return this._cancer;
}
set cancer(value: boolean) {
this._cancer = value;
}
get anosoEkthesi(): string {
return this._anosoEkthesi;
}
set anosoEkthesi(value: string) {
this._anosoEkthesi = value;
}
get bodyPart(): BodyPart {
return this._bodyPart;
}
set bodyPart(value: BodyPart) {
this._bodyPart = value;
}
}
Crazy or what??
Has anybody faced anything similar?? Any Ideas? I am bunging my head two days now with this... Something wrong with the Observable??
The problem was in the way i was getting the data. If you look closely to the screenshot the printed object is within a table [{object}]. So i changed the code from:
async openDialog(id: number) {
let incident: Incident;
this.subscriptions.push(
await this.incidentsService.getIncidentByID(id).subscribe(response => {
incident = response;
const dialogRef = this.dialog.open(IncidentDetailsComponent, {height: '900px', width: '900px', 'data': {'incident': response}});
}));
// const dialogRef = this.dialog.open(IncidentDetailsComponent, {height: '900px', width: '900px', 'data': {'incident': incident}});
}
To:
async openDialog(id: number) {
let incident: Incident;
this.subscriptions.push(
await this.incidentsService.getIncidentByID(id).subscribe(response => {
incident = response[0]; <-- HERE IS THE CHANGE
const dialogRef = this.dialog.open(IncidentDetailsComponent, {height: '900px', width: '900px', 'data': {'incident': response}});
}));
// const dialogRef = this.dialog.open(IncidentDetailsComponent, {height: '900px', width: '900px', 'data': {'incident': incident}});
}
And everything Worked. So stupid of me....

Angular-Calendar context menu not working how to bring up?

I am trying to integrate the angular-calendar context menu from here..
https://mattlewis92.github.io/angular-calendar/#/context-menu on of the child module called Calendar integrates it.
after installing all necessary module, the context-menu not working for me.
here is my child module :
import { NgModule } from '#angular/core';
import { BrowserAnimationsModule } from '#angular/platform-browser/animations';
import { HttpClientModule } from "#angular/common/http";
import { CalendarModule, DateAdapter } from 'angular-calendar';
import { ContextMenuModule } from 'ngx-contextmenu';
import { adapterFactory } from 'angular-calendar/date-adapters/date-fns';
import { CommonModule } from '#angular/common';
import { RouterModule, Routes } from '#angular/router';
import { StoreModule } from '#ngrx/store';
import { EffectsModule } from '#ngrx/effects';
import { reducerCalendar } from "./state/calendar.reducer";
import { EffectsEvents } from "./state/calendar.effects";
import { IboCalendarComponent } from './components/ibo-calendar/ibo-calendar.component';
import { IboCalendarHeaderComponent } from './ibo-calendar-header/ibo-calendar-header.component';
import { CalendarShellComponent } from './containers/calendar-shell/calendar-shell.component';
import { SharedModule } from "./../shared-components/shared.module";
const iboCalenderRoutes: Routes = [
// { path: '', redirectTo:'setupConfig', pathMatch:'full' },
{ path: 'iboCalendar', component: CalendarShellComponent }
];
#NgModule({
declarations: [IboCalendarComponent, IboCalendarHeaderComponent, CalendarShellComponent],
imports: [
CommonModule,
BrowserAnimationsModule,
HttpClientModule,
SharedModule,
CalendarModule.forRoot({
provide: DateAdapter,
useFactory: adapterFactory
}),
ContextMenuModule.forRoot({
useBootstrap4: true
}),
RouterModule.forChild(iboCalenderRoutes),
EffectsModule.forFeature([EffectsEvents]),
StoreModule.forFeature('reducerCalendar', reducerCalendar)
],
exports: [ ]
})
export class iboCalendarModule { }
here is the ts file :
import { Component, OnInit, ChangeDetectionStrategy, Input, OnChanges } from '#angular/core';
import { CalendarService } from "./../../services/calendar.service";
import { ModelEvent, EventState } from "./../../models/model.event";
import { CalendarEvent } from 'angular-calendar';
import { Observable, Subject } from 'rxjs';
import { colors } from "./../../utilities/colors";
import { tap } from 'rxjs/operators';
declare var $:any;
#Component({
selector: 'ibo-calendar',
templateUrl: './ibo-calendar.component.html',
styleUrls: ['./ibo-calendar.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class IboCalendarComponent implements OnChanges,OnInit {
view: string = 'month';
// viewDate: Date = new Date('August 19, 2018');
viewDate: Date = new Date()
#Input() events:ModelEvent[];
#Input() currentEvent: ModelEvent;
refresh: Subject<any> = new Subject();
constructor() { }
ngOnInit() {
const headerHeight = $('.site-header').outerHeight();
//moving content down to header
$('body').css({paddingTop: headerHeight});
}
ngOnChanges() {
if( this.currentEvent ) {
this.viewDate = new Date(this.currentEvent.start);
}
}
eventClicked({ event }: { event: CalendarEvent }): void {
console.log('Event clicked', event);
}
addEvent(date:Date):void {
console.log('date is', date);
this.events.push({
id : 0,
start : date,
title : 'New Event',
end : new Date(),
allDay : false
})
this.refresh.next();
}
}
here is the template file :
<div class="container-fluid site-content">
<ibo-calendar-header [(view)]="view" [(viewDate)]="viewDate"></ibo-calendar-header>
<context-menu #basicMenu>
<ng-template contextMenuItem (execute)="addEvent($event.item)">
Add event
</ng-template>
</context-menu>
<ng-template
#monthCellTemplate
let-day="day"
let-openDay="openDay"
let-locale="locale"
let-tooltipPlacement="tooltipPlacement"
let-highlightDay="highlightDay"
let-unhighlightDay="unhighlightDay"
let-eventClicked="eventClicked"
>
<div
class="fill-height"
[contextMenu]="basicMenu"
[contextMenuSubject]="day.date"
>
<div class="cal-cell-top">
<span class="cal-day-badge" *ngIf="day.badgeTotal > 0"
>{{ day.badgeTotal }}</span
>
<span class="cal-day-number"
>{{ day.date | calendarDate:'monthViewDayNumber':locale }}</span
>
</div>
<div class="cal-events">
<div
class="cal-event"
*ngFor="let event of day.events"
[style.backgroundColor]="event.color.primary"
[ngClass]="event?.cssClass"
(mouseenter)="highlightDay.emit({event: event})"
(mouseleave)="unhighlightDay.emit({event: event})"
[mwlCalendarTooltip]="event.title | calendarEventTitle:'monthTooltip':event"
[tooltipPlacement]="tooltipPlacement"
(click)="$event.stopPropagation(); eventClicked.emit({event: event})"
></div>
</div>
</div>
</ng-template>
<ng-template
#weekHeaderTemplate
let-days="days"
let-locale="locale"
let-dayHeaderClicked="dayHeaderClicked"
>
<div class="cal-day-headers">
<div
class="cal-header"
*ngFor="let day of days"
[class.cal-past]="day.isPast"
[class.cal-today]="day.isToday"
[class.cal-future]="day.isFuture"
[class.cal-weekend]="day.isWeekend"
(click)="dayHeaderClicked.emit({day: day})"
[contextMenu]="basicMenu"
[contextMenuSubject]="day.date"
>
<b>{{ day.date | calendarDate:'weekViewColumnHeader':locale }}</b><br />
<span
>{{ day.date | calendarDate:'weekViewColumnSubHeader':locale }}</span
>
</div>
</div>
</ng-template>
<ng-template #dayHourSegmentTemplate let-segment="segment" let-locale="locale">
<div
class="cal-hour-segment"
[ngClass]="segment.cssClass"
[contextMenu]="basicMenu"
[contextMenuSubject]="segment.date"
>
<div [hidden]="!segment.isStart" class="cal-time">
{{ segment.date | calendarDate:'dayViewHour':locale }}
</div>
</div>
</ng-template>
<div class="alert alert-info">
Click on a day on the view.
<strong *ngIf="clickedDate">You clicked on this day: {{ clickedDate | date:'medium' }}</strong>
</div>
<div>
<div [ngSwitch]="view">
<mwl-calendar-month-view *ngSwitchCase="'month'" [viewDate]="viewDate"
[events]="events" (eventClicked)="eventClicked($event)" (dayClicked)="clickedDate = $event.day.date">
</mwl-calendar-month-view>
<mwl-calendar-week-view *ngSwitchCase="'week'"
[viewDate]="viewDate" [events]="events" (eventClicked)="eventClicked($event)" (dayHeaderClicked)="clickedDate = $event.day.date">
</mwl-calendar-week-view>
<mwl-calendar-day-view *ngSwitchCase="'day'"
[viewDate]="viewDate" [events]="events" (eventClicked)="eventClicked($event)">
</mwl-calendar-day-view>
</div>
</div>
</div>
Getting no errors as well.
any one guide me? thanks in advance.

`#ngrx/store` - createFeatureSelector never called from wrapper component

Here is my createFeatureSelector ts file :
import { State } from "./../../state/app.state";
import { EventState, ModelEvent } from "./../models/model.event";
import { createFeatureSelector, createSelector, ActionReducerMap } from "#ngrx/store";
export interface NewState extends State {
events:EventState
}
const getCalendarFeatureState = createFeatureSelector<EventState>("reducer");
export const getEvents = createSelector(getCalendarFeatureState, state => state.events );
my events shell component ( where i call the getEvents ):
import { Component, OnInit, ChangeDetectionStrategy } from '#angular/core';
import { Store, select } from '#ngrx/store';
import { Observable } from 'rxjs';
import * as fromRoot from "./../../state";
import { CalendarActions, Load } from "./../../state/calendar.actions";
import { ModelEvent, EventState } from "./../../models/model.event";
#Component({
selector: 'calendar-shell',
templateUrl: './calendar-shell.component.html',
changeDetection:ChangeDetectionStrategy.OnPush
})
export class CalendarShellComponent implements OnInit {
events$:Observable<any>
constructor(private store:Store<fromRoot.NewState>) { }
ngOnInit():void{
this.store.dispatch(new Load());
this.events$ = this.store.pipe(select(fromRoot.getEvents)); //getting nothing!!
}
}
template :
<div *ngIf="events$ | async"> //shows nothing!!
<ul>
<li *ngFor="let item of events">{{item.title}}</li>
</ul>
</div>
Any help? thanks in advance. ( ready to provide further details if any )
I update the dom element like this:
<div *ngIf="events$ | async"> //shows nothing!!
<ul>
<li *ngFor="let item of events | async">{{item.title}}</li>
</ul>
</div>
works fine.

custom mapping json file in angular 6 from rails api project

I'm new to Angular and I'm having a problem with map data from my Rails app to the Angular app. I know I need to do some customisation to the code, but I don't really know how.
I want to mention that I'm using Rails 5.2 and Active Model Serializer for the json request.
In my rails app I have Course,Segment,Quiz,Video models and the relations are:
Course had many Segments
Segments can be Quiz or Video and I use STI so the quizzes and videos
are in segments table
This is the json file I get from the rails app and I want to map:
[
{
"id":1,
"title":"Introduction",
"author":"Dana Inbar",
"segments":[
{
"id":1,
"name":"Intro01",
"data":"http://www.video.com/1/1"
},
{
"id":2,
"name":"Intro02",
"data":"http://www.video.com/1/2"
},
{
"id":3,
"name":"Intro03",
"data":"[
{
"question 1" : "___",
"answers" : {
"1" : "____",
"2" : "____",
"3" : "____"
},
"correct_answer" : "2"
},
]"
}
]
},
{
"id":2,
"title":"Master the ELN",
"author":"Dana Inbar",
"segments":[
]
},
{
"id":3,
"title":"Master the Inventory",
"author":"Dana Inbar",
"segments":[
]
}
]
This are my angular files:
app.module
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { HttpClientModule } from '#angular/common/http';
import { RouterModule, Routes } from '#angular/router';
import { FormsModule } from '#angular/forms';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { CourseModule } from './courses/course.module';
import { CourseService } from './courses/course.service';
#NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
HttpClientModule,
AppRoutingModule,
CourseModule,
FormsModule
],
providers: [CourseService],
bootstrap: [AppComponent]
})
export class AppModule { }
courses/course
export interface IQuiz {}
export interface IVideo {}
export interface ISegment {
segment_id: string;
name: string;
type: string;
data: string;
}
export interface ICourse {
course_id: number;
title: string;
autor: string;
segments: {
[segment_id: string]: ISegment,
[name: string]: ISegment,
[type: string]: ISegment,
[data: string]: ISegment
}
}
courses/course.service
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { Observable, throwError } from 'rxjs';
import { map, tap, catchError } from 'rxjs/operators';
import { ICourse } from './course';
// Inject Data from Rails app to Angular app
#Injectable()
export class CourseService{
private courseUrl = 'http://localhost:3000/courses.json';
constructor(private http: HttpClient) { }
// Get Courses from Rails API App
getCourses(): Observable<ICourse[]> {
return this.http.get<ICourse[]>(this.courseUrl)
.map((res: Response) => res.json()data)
.catch(this.handleError);
}
// Handle Any Kind of Errors
private handleError(error: Response) {
console.error(error);
return Observable.throw(error.json().error || 'Server Error');
}
}
courses/course.module
import { NgModule } from '#angular/core';
import { CommonModule } from '#angular/common';
import { RouterModule, Routes } from '#angular/router';
import { MatSidenavModule } from '#angular/material/sidenav';
import { BrowserAnimationsModule } from '#angular/platform-browser/animations';
import { CourseListComponent } from './course-list/course-list.component';
import { CourseDetailComponent } from './course-detail/course-detail.component';
import { CourseService } from './course.service';
import { CoursePlayComponent } from './course-play/course-play.component';
const coursesRoutes: Routes = [
{ path: 'courses', component: CourseListComponent },
{ path: 'courses/:id', component: CourseDetailComponent },
{ path: 'courses/:id/1', component: CoursePlayComponent }
]
#NgModule({
imports: [
CommonModule,
MatSidenavModule,
BrowserAnimationsModule,
RouterModule.forChild(
coursesRoutes
)
],
declarations: [
CourseListComponent,
CourseDetailComponent,
CoursePlayComponent
],
providers: [
CourseService
]
})
export class CourseModule { }
courses/course-list/course-list.component
import { Component, OnInit } from '#angular/core';
import { ActivatedRoute, Router } from '#angular/router';
import { ICourse } from '../course';
import { CourseService } from '../course.service';
#Component({
selector: 'lg-course-list',
templateUrl: './course-list.component.html',
styleUrls: ['./course-list.component.sass']
})
export class CourseListComponent implements OnInit {
pageTitle = "LabGuru Academy";
courses: ICourse[] =[];
errorMessage: string;
constructor(private courseService: CourseService) { }
ngOnInit() {
this.courseService.getCourses()
.subscribe(
courses => this.courses = courses,
errorMessage => this.errorMessage = <any>error
);
}
}
courses/course-list/course-list.html
<div class="row mt-3 no-gutters">
<div class="col-lg-8">
<img src="./assets/images/lg-purple.png" class="d-inline-block align-top" alt="">
</div>
</div>
<div class="jumbotron">
<div class="container text-center">
<h1>{{pageTitle}}</h1>
</div>
</div>
<div class="container-fluid bg-3 text-center">
<div class="row justify-content-lg-center">
<div class="col-sm-3" *ngFor="let course of courses | async">
<div class="card">
<div class="card-body">
<h3 class="card-title">{{course.title}}</h3>
<p class="card-text"><small class="text-muted">6 Lessons</small></p>
</div>
</div>
</div>
</div>
</div>
<br><br>
courses/course-list/course-list.sass
$pos: 70px
$color: #5c0099
$bg-col: #FFFFFF
$hig: 15rem
$wid: 15rem
$left: 5%
$top: 30%
$right: 7%
.jumbotron
background-color: transparent
color: $color
.col-sm-3
position: relative
min-height: 1px
padding-left: $left
outline-offset: none
.card
border-color: $color
background-color: $bg-col
width: $wid
height: $hig
.card-title
position: absolute
text-align: center
padding: inherit
.card-text
position: absolute
bottom: $left
right: $right

Identifier 'categoryName' is not defined. 'Array' does not contain such a member

<div class="example-container">
<div class="pb-16" fxLayout="row" fxLayoutAlign="start center">
<div class="h2 secondary-text">
<b>
<u>Profile Details of {{rows ? rows?.categoryName : ''}}</u>
</b>
</div>
</div>
<br />
<mat-form-field>
<mat-label>Category Name</mat-label>
<input matInput placeholder="category name" value="{{rows ? rows?.categoryName : ''}}">
</mat-form-field>
<br />
<br />
<mat-form-field class="example-full-width">
<mat-label>Category Description</mat-label>
<textarea matInput placeholder="category description" value="{{rows ? rows?.categoryDesc : ''}}"></textarea>
</mat-form-field>
</div>
This is component.html
import { Component,OnInit,Input } from "#angular/core";
import { MatSnackBar } from '#angular/material';
import { coerceBooleanProperty } from "#angular/cdk/coercion";
import { HttpClient } from "#angular/common/http";
import { ActivatedRoute } from "#angular/router";
import { FormBuilder, FormGroup, Validators,FormControl } from
'#angular/forms';
import { Location} from '#angular/common';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/delay';
import 'rxjs/add/operator/map';
import {ServiceContactsFakeDb} from '../../../../../fuse-fake-db/service-
contacts';
import { Data } from '../../../../../fuse-fake-db/hero';
import { LIST } from '../../../../../fuse-fake-db/mock-heroes';
import {CategoryService} from "../category.service";
#Component({
selector: 'profile-detail',
templateUrl: './profile.component.html',
styleUrls:['./component.scss'],
providers:[CategoryService]
})
export class ProfileComponent implements OnInit {
constructor (private location:Location,private http: HttpClient,private
service:CategoryService,private _Activatedroute:ActivatedRoute){
}
name = new FormControl('', [Validators.required]);
name1 = new FormControl('', [Validators.required]);
favoriteSeason: any;
_card = false;
profiles = LIST;
#Input() category;
selectedProfile: Data;
rawdata:any[];
rows: any[];
reorderable = true;
categoryName : any[];
categoryDesc : any = {};
data = [];
item:string[];
id:string;
catName: string;
catDesc: string;
//selectedProfile: ServiceContactsFakeDb;
setDataLayoutType(value: boolean) {
this._card = coerceBooleanProperty(value);
}
ngOnInit(){
// this.getDetail();
this.id=this._Activatedroute.snapshot.params['id'];
console.log(this.id);
this.service.getcategory().subscribe(res => {
this.rawdata = res;
for(var i=0;i<this.rawdata.length;i++){
if(this.id == this.rawdata[i].id){
this.rows=this.rawdata[i];
console.log(this.rows);
}
}
});
}
In this code I am getting error in component.html file like this :
[Angular] Identifier 'categoryName' is not defined. 'Array' does not contain such a member .
I am fetching the values from an api, I am getting the output but still it shows errors in this line "value="{{rows ? rows?.categoryName : ''}}"
I had defined rows as a array replace it with rows: any={} instead of rows: any[];

Resources