Skip to content

Instantly share code, notes, and snippets.

@nirkaufman
Created April 9, 2020 23:59
Show Gist options
  • Save nirkaufman/5a3d450046bb16a17b41ff275e6dc0e4 to your computer and use it in GitHub Desktop.
Save nirkaufman/5a3d450046bb16a17b41ff275e6dc0e4 to your computer and use it in GitHub Desktop.
import {
ChangeDetectorRef,
Component,
ComponentFactory,
ComponentFactoryResolver,
ElementRef,
Injector,
OnInit,
Renderer2,
ViewChild,
ViewContainerRef
} from '@angular/core';
import {WidgetComponent} from "./widget.component";
@Component({
selector: 'nk-layout',
template: `
<div class="row">
<div class="col left-area">
<h4>Rate Area</h4>
<ng-container #leftSide></ng-container>
</div>
<div class="col">
<h4>Create & Edit Area</h4>
<div class="form-group">
<input class="form-control"
#inputRef
placeholder="Widget Title"
[(ngModel)]="widgetTitle"
(keydown.enter)="stopEdit()"
name="title">
</div>
<button (click)="createWidget()" class="btn btn-primary mr-1">Create</button>
<button (click)="removeAll()" class="btn btn-danger">remove all</button>
<ng-container #rightSide></ng-container>
</div>
</div>
`,
styles: ['.edit {border-color: red}']
})
export class LayoutComponent implements OnInit {
@ViewChild('rightSide', {read: ViewContainerRef}) rightSide: ViewContainerRef;
@ViewChild('leftSide', {read: ViewContainerRef}) leftSide: ViewContainerRef;
@ViewChild('inputRef') inputRef: ElementRef;
private widgetFactory: ComponentFactory<WidgetComponent>;
private _titleValue: string;
selectedWidget: WidgetComponent;
constructor(
private componentFactoryResolver: ComponentFactoryResolver,
private renderer: Renderer2,
private changeDetectorRef: ChangeDetectorRef,
private injector: Injector) {
}
// factory should be created only once
ngOnInit(): void {
this.widgetFactory = this.componentFactoryResolver.resolveComponentFactory(WidgetComponent);
this.resetLayoutState();
}
set widgetTitle(newTitle: string) {
this._titleValue = newTitle;
if (this.selectedWidget) {
this.selectedWidget.title = this._titleValue;
}
}
get widgetTitle() {
return this._titleValue;
}
// create a widget and insert it to the right side
createWidget() {
const widgetComponent = this.widgetFactory.create(this.injector)
const widgetViewRef = this.rightSide.insert(widgetComponent.hostView);
// pass the widget data
widgetComponent.instance.title = this.widgetTitle;
widgetComponent.instance.viewRef = widgetViewRef;
widgetComponent.instance.switch = this.switch.bind(this);
widgetComponent.instance.edit = this.edit.bind(this);
// reset widget data
this.resetLayoutState();
}
// detach from one view container and attach to another
switch(widget: WidgetComponent) {
const widgetViewRef = widget.viewRef;
if (this.rightSide.indexOf(widgetViewRef) >= 0) {
widget.viewRef = this.leftSide.insert(this.rightSide.detach(this.rightSide.indexOf(widgetViewRef)));
this.resetLayoutState();
}
if (this.leftSide.indexOf(widgetViewRef) >= 0) {
widget.viewRef = this.rightSide.insert(this.leftSide.detach(this.leftSide.indexOf(widgetViewRef)));
this.selectedWidget = widget;
this.widgetTitle = widget.title;
}
}
edit(widget: WidgetComponent) {
// prevent editing when on the left side
if (this.leftSide.indexOf(widget.viewRef) < 0) {
this.selectedWidget = widget;
this.widgetTitle = this.selectedWidget.title;
this.renderer.addClass(this.inputRef.nativeElement, 'edit',);
}
}
stopEdit() {
this.resetLayoutState();
this.renderer.removeClass(this.inputRef.nativeElement, 'edit');
}
removeAll() {
this.rightSide.clear();
this.leftSide.clear();
}
private resetLayoutState() {
this.selectedWidget = null;
this.widgetTitle = '';
}
}
import {Component, Input, OnInit, ViewRef} from '@angular/core';
@Component({
selector: 'nk-widget',
template: `
<div class="card my-3">
<div class="card-body">
<h5 class="card-title">{{title}} {{count}}</h5>
<button (click)="increase()" class="btn btn-sm btn-success mr-1">UP</button>
<button (click)="decrement()" class="btn btn-sm btn-info mr-1">DOWN</button>
<button (click)="switch(this)" class="btn btn-sm btn-outline-primary mr-1 ">Switch</button>
<button (click)="edit(this)" class="btn btn-sm btn-outline-danger mr-1">Edit</button>
<div>
</div>
</div>
</div>
`,
})
export class WidgetComponent implements OnInit {
@Input() title: string;
count: number;
viewRef: ViewRef;
switch: Function;
edit: Function;
ngOnInit(): void {
this.count = 0;
}
increase() {
this.count++;
}
decrement() {
this.count--;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment