Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*/

import { AsyncPipe } from '@angular/common';
import { Component, Input, OnInit } from '@angular/core';
import { Component, input, OnInit } from '@angular/core';
import { SiChartCartesianComponent } from '@siemens/charts-ng/cartesian';
import { WidgetConfig, WidgetInstance } from '@siemens/dashboards-ng';
import { ContentActionBarMainItem } from '@siemens/element-ng/content-action-bar';
Expand All @@ -25,7 +25,7 @@ export interface WidgetChartCartesianConfig {
templateUrl: './chart-widget.component.html'
})
export class ChartWidgetComponent implements OnInit, WidgetInstance {
@Input() config!: WidgetConfig;
readonly config = input.required<WidgetConfig>();
primaryActions: ContentActionBarMainItem[] = [
{ type: 'action', label: 'Print', action: () => alert('do print') }
];
Expand All @@ -45,7 +45,7 @@ export class ChartWidgetComponent implements OnInit, WidgetInstance {
}

get cartesianConfig(): WidgetChartCartesianConfig {
return this.config.payload.config as WidgetChartCartesianConfig;
return this.config().payload.config as WidgetChartCartesianConfig;
}

private getCartesianChartData(): Observable<CartesianChartData> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
DestroyRef,
HostListener,
inject,
Input,
model,
output,
signal
} from '@angular/core';
Expand Down Expand Up @@ -41,10 +41,7 @@ import { SiFormModule } from '@siemens/element-ng/form';
templateUrl: './contact-widget-editor.component.html'
})
export class ContactWidgetEditorComponent implements WidgetInstanceEditorWizard, AfterViewInit {
@Input({
required: true
})
config!: WidgetConfig;
readonly config = model.required<Omit<WidgetConfig, 'id'>>();
readonly statusChanges = output<Partial<WidgetConfigStatus>>();

get state(): WidgetInstanceEditorWizardState {
Expand Down Expand Up @@ -82,25 +79,25 @@ export class ContactWidgetEditorComponent implements WidgetInstanceEditorWizard,
// must emit initial state
this.stateChange.emit(this.state);

const date: Date = new Date(this.config?.payload?.birthday);
const date: Date = new Date(this.config()?.payload?.birthday);
this.personal.patchValue({
firstName: this.config?.payload?.firstName ?? '',
lastName: this.config?.payload?.lastName ?? '',
firstName: this.config()?.payload?.firstName ?? '',
lastName: this.config()?.payload?.lastName ?? '',
birthday: !isNaN(date.getTime()) ? date : ''
});
this.company.patchValue({
jobTitle: this.config?.payload?.jobTitle ?? '',
company: this.config?.payload?.company ?? '',
email: this.config?.payload?.email ?? '',
phone: this.config?.payload?.phone ?? ''
jobTitle: this.config()?.payload?.jobTitle ?? '',
company: this.config()?.payload?.company ?? '',
email: this.config()?.payload?.email ?? '',
phone: this.config()?.payload?.phone ?? ''
});

this.form.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(value => {
const config = this.config;
const config = this.config();

Object.assign(config.payload, value.personal);
Object.assign(config.payload, value.company);
this.config = { ...config };
this.config.set({ ...config });
if (!this.modified) {
this.modified = true;
this.statusChanges.emit({ modified: this.modified });
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@let payload = config.payload;
@let payload = config().payload;
<h3 class="si-h1-bold" bold>{{ payload.firstName }} {{ payload.lastName }}</h3>
<dl class="mt-6 mb-0">
@if (payload.birthday) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* SPDX-License-Identifier: MIT
*/
import { DatePipe } from '@angular/common';
import { Component, Input } from '@angular/core';
import { Component, input } from '@angular/core';
import { WidgetConfig, WidgetInstance } from '@siemens/dashboards-ng';
@Component({
selector: 'app-contact-widget',
Expand All @@ -12,6 +12,5 @@ import { WidgetConfig, WidgetInstance } from '@siemens/dashboards-ng';
styleUrl: './contact-widget.component.scss'
})
export class ContactWidgetComponent implements WidgetInstance {
@Input({ required: true })
readonly config!: WidgetConfig;
readonly config = input.required<WidgetConfig>();
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Copyright (c) Siemens 2016 - 2025
* SPDX-License-Identifier: MIT
*/
import { Component, Input, OnInit, output } from '@angular/core';
import { Component, model, OnInit, output } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { WidgetConfig, WidgetConfigStatus, WidgetInstanceEditor } from '@siemens/dashboards-ng';

Expand All @@ -12,20 +12,23 @@ import { WidgetConfig, WidgetConfigStatus, WidgetInstanceEditor } from '@siemens
templateUrl: './note-widget-editor.component.html'
})
export class NoteWidgetEditorComponent implements WidgetInstanceEditor, OnInit {
@Input() config!: WidgetConfig | Omit<WidgetConfig, 'id'>;
readonly config = model.required<WidgetConfig | Omit<WidgetConfig, 'id'>>();

readonly statusChanges = output<Partial<WidgetConfigStatus>>();

protected heading = '';
protected message = '';

ngOnInit(): void {
this.heading = this.config?.heading ?? '';
this.message = this.config?.payload?.message ?? '';
this.heading = this.config()?.heading ?? '';
this.message = this.config()?.payload?.message ?? '';
}

onChange(): void {
this.config!.heading = this.heading ?? '';
this.config!.payload.message = this.message ?? '';
this.statusChanges.emit({ invalid: this.config!.heading.trim().length === 0, modified: true });
const config = this.config();
config!.heading = this.heading ?? '';
config!.payload.message = this.message ?? '';
this.statusChanges.emit({ invalid: config!.heading.trim().length === 0, modified: true });
this.config.set(config);
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<p>{{ config.payload?.message ?? '' }}</p>
<p>{{ config().payload?.message ?? '' }}</p>
@if (editable) {
<p>Click edit to configure this web-component widget.</p>
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Copyright (c) Siemens 2016 - 2025
* SPDX-License-Identifier: MIT
*/
import { Component, EventEmitter, Input, OnInit } from '@angular/core';
import { Component, EventEmitter, input, OnInit } from '@angular/core';
import { WidgetConfig, WidgetConfigEvent, WidgetInstance } from '@siemens/dashboards-ng';
import { ContentActionBarMainItem } from '@siemens/element-ng/content-action-bar';
import { MenuItem } from '@siemens/element-ng/menu';
Expand All @@ -12,8 +12,8 @@ import { MenuItem } from '@siemens/element-ng/menu';
templateUrl: './note-widget.component.html'
})
export class NoteWidgetComponent implements WidgetInstance, OnInit {
@Input() config!: WidgetConfig;
@Input() editable = false;
readonly config = input.required<WidgetConfig>();
editable = false;

primaryActions: ContentActionBarMainItem[] = [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import {
Component,
input,
Input,
model,
NO_ERRORS_SCHEMA,
OnInit,
Expand Down Expand Up @@ -55,13 +54,13 @@ export class SiWidgetCatalogMockComponent extends SiWidgetCatalogComponent imple
template: ''
})
export class SiDashboardToolbarStubComponent {
@Input() primaryEditActions: MenuItem[] = [];
@Input() secondaryEditActions: MenuItem[] = [];
@Input() disableSaveButton = false;
@Input() disabled = false;
@Input() editable = false;
@Input() hideEditButton = false;
@Input() showEditButtonLabel = false;
readonly primaryEditActions = input<MenuItem[]>([]);
readonly secondaryEditActions = input<MenuItem[]>([]);
readonly disableSaveButton = input(false);
readonly disabled = input(false);
readonly editable = input(false);
readonly hideEditButton = input(false);
readonly showEditButtonLabel = input(false);
}

@Component({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export class SiWebComponentEditorWrapperComponent
this.webComponent?.addEventListener('stateChange', this.webComponentStateChangeListener);
this.webComponent?.addEventListener('statusChanges', this.webComponentStatusChangesListener);
this.webComponent?.addEventListener('configChange', this.webComponentEventListener);
this.webComponentHost.nativeElement.appendChild(this.webComponent);
this.webComponentHost().nativeElement.appendChild(this.webComponent);
}

ngOnDestroy(): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,50 +6,56 @@ import {
AfterViewInit,
ElementRef,
inject,
Input,
Renderer2,
ViewChild,
DOCUMENT,
Directive
Directive,
input,
viewChild,
SimpleChanges,
OnChanges
} from '@angular/core';

import { WidgetConfig, WidgetInstance, WidgetInstanceEditor } from '../../model/widgets.model';

@Directive()
export abstract class SiWebComponentWrapperBaseComponent<
T extends WidgetInstance | WidgetInstanceEditor
> implements AfterViewInit {
private _config!: WidgetConfig;
get config(): WidgetConfig {
return this._config;
}
>
implements AfterViewInit, OnChanges
{
readonly config =
input.required<
T extends WidgetInstance ? WidgetConfig : WidgetConfig | Omit<WidgetConfig, 'id'>
>();

@Input() set config(config: WidgetConfig) {
this._config = config;
if (this.webComponent) {
this.webComponent.config = config;
}
}
readonly elementTagName = input.required<string>();
readonly url = input.required<string>();

protected readonly webComponentHost = viewChild.required('webComponentHost', {
read: ElementRef
});

@Input() elementTagName!: string;
@Input() url!: string;
@ViewChild('webComponentHost', { static: true, read: ElementRef })
protected webComponentHost!: ElementRef;
protected webComponent?: HTMLElement & T;

private renderer2 = inject(Renderer2);
private document = inject(DOCUMENT);

ngOnChanges(changes: SimpleChanges): void {
if (changes.config && this.webComponent) {
this.webComponent.config = this.config();
}
}

ngAfterViewInit(): void {
if (!this.isScriptLoaded(this.url)) {
if (!this.isScriptLoaded(this.url())) {
const script = this.renderer2.createElement('script');
script.src = this.url;
script.src = this.url();
this.renderer2.appendChild(this.document.body, script);
}

this.webComponent = this.renderer2.createElement(this.elementTagName);
this.webComponent = this.renderer2.createElement(this.elementTagName());
if (this.webComponent) {
this.webComponent.config = this.config;
this.webComponent.config = this.config();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Copyright (c) Siemens 2016 - 2025
* SPDX-License-Identifier: MIT
*/
import { AfterViewInit, Component, EventEmitter, Input, OnDestroy } from '@angular/core';
import { AfterViewInit, Component, EventEmitter, OnDestroy } from '@angular/core';
import { MenuItem as MenuItemLegacy } from '@siemens/element-ng/common';
import { ContentActionBarMainItem } from '@siemens/element-ng/content-action-bar';
import { MenuItem } from '@siemens/element-ng/menu';
Expand All @@ -23,7 +23,7 @@ export class SiWebComponentWrapperComponent
return this._editable ?? false;
}

@Input() set editable(editable: boolean) {
set editable(editable: boolean) {
this._editable = editable;
if (this.webComponent) {
this.webComponent.editable = editable;
Expand All @@ -43,7 +43,7 @@ export class SiWebComponentWrapperComponent
override ngAfterViewInit(): void {
super.ngAfterViewInit();
this.webComponent?.addEventListener('configChange', this.webComponentEventListener);
this.webComponentHost.nativeElement.appendChild(this.webComponent);
this.webComponentHost().nativeElement.appendChild(this.webComponent);
}

ngOnDestroy(): void {
Expand Down
4 changes: 2 additions & 2 deletions projects/dashboards-ng/src/widget-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,8 @@ const loadAndAttachWebComponentWrapper = (
} else {
widgetInstanceRef = host.createComponent(SiWebComponentEditorWrapperComponent);
}
widgetInstanceRef.instance.elementTagName = factory[componentName];
widgetInstanceRef.instance.url = factory.url;
widgetInstanceRef.setInput('elementTagName', factory[componentName]);
widgetInstanceRef.setInput('url', factory.url);
result.next(widgetInstanceRef);
result.complete();
} else {
Expand Down
Loading