I have an Angular template and component that I've adapted from Angular Material's dashboard schematic.
I would like to manipulate some of the properties on cards using events and two-way data binding. At first glance, two-way data binding seems to work, as I can manipulate the editorContent property of a given index in the card using directives, and those changes are reflected in a simple
tag that I've added to the view for debugging. However, this doesn't appear to actually update the cards object in the component.
I've read that to manipulate observables, you must subscribe to them first. The clearEditor method successfully gets the data from cards, but the contentEditor is not updated from the view, and setting it to null in the method does not appear to change the value of cards either, if I were to set it to a string that is not empty or null in the constructor.
import {
Component
} from "@angular/core";
import {
map
} from "rxjs/operators";
import {
Breakpoints,
BreakpointObserver
} from "@angular/cdk/layout";
import {
Observable
} from 'rxjs';
@Component({
selector: "app-repl",
templateUrl: "./repl.component.html",
styleUrls: ["./repl.component.scss"]
})
export class REPLComponent {
cards: Observable < any > ;
constructor(private breakpointObserver: BreakpointObserver) {
this.cards = this.breakpointObserver.observe(Breakpoints.Handset).pipe(
map(({
matches
}) => {
if (matches) {
return [{
title: "HTML",
content: "code",
language: "html",
cols: 1,
rows: 1,
editorContent: ""
},
{
title: "CSS",
content: "code",
language: "css",
cols: 1,
rows: 1,
editorContent: ""
},
{
title: "PDF",
content: "pdf",
cols: 1,
rows: 1
}
];
}
return [{
title: "HTML",
content: "code",
language: "html",
cols: 1,
rows: 1,
editorContent: ""
},
{
title: "PDF",
content: "pdf",
cols: 1,
rows: 2
},
{
title: "CSS",
content: "code",
language: "css",
cols: 1,
rows: 1,
editorContent: ""
}
];
})
);
}
clearEditor(language: string) {
this.cards.subscribe(cards => {
cards.forEach(function(card) {
if (card.language === language) {
card.editorContent = null;
}
});
});
}
}
<div class="grid-container">
<h1 class="mat-h1">REPL</h1>
<mat-grid-list cols="2" rowHeight="400px">
<mat-grid-tile *ngFor="let card of cards | async" [colspan]="card.cols" [rowspan]="card.rows">
<mat-card class="dashboard-card">
<mat-card-header>
<mat-card-title>
{{card.title}}
<button *ngIf="card.content==='code'" mat-icon-button class="more-button" [matMenuTriggerFor]="menu" aria-label="Toggle menu">
<mat-icon>more_vert</mat-icon>
</button>
<mat-menu #menu="matMenu" xPosition="before">
<button mat-menu-item (click)="clearEditor(card.language)">Clear</button>
<button mat-menu-item>Download</button>
</mat-menu>
</mat-card-title>
</mat-card-header>
<mat-card-content *ngIf="card.content==='code'">
<td-code-editor style="height: 300px" theme="vs-dark" flex [language]="card.language" [(ngModel)]="card.editorContent"></td-code-editor>
<p>{{card.editorContent}}</p>
</mat-card-content>
<mat-card-content *ngIf="card.content==='pdf'">
<pdf-viewer src="\assets\document.pdf" style="display: block; max-width: 490px; max-height: 100%;" [render-text]="false" [original-size]="false" [autoresize]="true" [show-all]="false" [page]="1">
</pdf-viewer>
</mat-card-content>
</mat-card>
</mat-grid-tile>
</mat-grid-list>
<button mat-button>
<mat-icon>cloud_upload</mat-icon>
Generate PDF
</button>
<button mat-button>
<mat-icon>save_alt</mat-icon>
Download PDF
</button>
</div>