projects/i-components/src/lib/components/xam-grid-column/xam-grid-column.component.ts
Pipe for applying format strings over text columns
Name | xamFormatString |
transform | |||||||||||||||
transform(format?: string, converter?: IValueConverter, columnModel?: any, dataType?: string)
|
|||||||||||||||
Generates a formatter function for the underlying columns based on the passed format string or ValueConverter.
Parameters :
Returns :
(value: any, rowData: any) => any
|
import {
AfterContentInit,
Component,
ContentChild,
ContentChildren,
ElementRef,
EventEmitter,
Inject,
Input,
LOCALE_ID,
OnInit,
Output,
Pipe,
PipeTransform,
QueryList,
TemplateRef,
} from '@angular/core';
import {
HorizontalAlignment,
ModelProxy,
VerticalAlignment,
XamGridCheckboxColumnModel,
XamGridColumnModel,
XamGridTemplateColumnModel,
XamGridTextColumnModel,
XamGridUnboundColumnModel,
DataTemplate,
TextWrapping,
RuntimeStyleInfo,
BindingInfo,
ColumnWidth,
IValueConverter,
XamGridGroupColumnModel,
smColorToCssColor,
FrameworkElement,
simpleStringFormat,
XamGridModel,
DependencyObject,
calculateBindingValue,
createBindingFromBindingInfo,
isResourceKeyValue,
getResourceKeyValue,
resolveBindingContext,
DependencyProperty,
} from '@mobilize/wms-framework';
import { BaseWrapperComponent } from '../basewrapper/basewrapper.component';
import { TextBoxComponent } from '../text-box/text-box.component';
import { TextBlockComponent } from '../text-block/text-block.component';
import { Utils } from '../../utils/utilities';
/**
* Angular component imitating the footer template functionality in the Xam grid.
*
* @export
* @class XamGridColumnFooterComponent
*/
@Component({
selector: 'wm-column-footer',
template: `<ng-content></ng-content>`,
})
export class XamGridColumnFooterComponent {
/**
* Returns the templated control. Either a text block or a text box.
*
* @readonly
* @memberof XamGridColumnFooterComponent
*/
public get control() {
return this.textBox || this.textBlock;
}
/**
* TextBoxComponent
*
* @protected
* @type {TextBoxComponent}
* @memberof XamGridColumnFooterComponent
*/
@ContentChild(TextBoxComponent)
protected textBox: TextBoxComponent;
/**
* TextBlockComponent
*
* @protected
* @type {TextBlockComponent}
* @memberof XamGridColumnFooterComponent
*/
@ContentChild(TextBlockComponent)
protected textBlock: TextBlockComponent;
}
/**
* Angular Component for the Xam Grid Column Control
*
* @export
* @class XamGridColumnComponent
* @implements {OnInit}
* @implements {AfterContentInit}
*/
@Component({
selector: 'wm-xam-grid-column',
templateUrl: './xam-grid-column.component.html',
styleUrls: ['./xam-grid-column.component.css'],
})
export class XamGridColumnComponent
extends BaseWrapperComponent
implements OnInit, AfterContentInit
{
/**
* Object with XamGridComponent properties and events.
*
* @type {*}
* @memberof XamGridColumnComponent
*/
@Input()
public model: XamGridColumnModel;
/**
* Gets or sets the style to be applied to the column header.
*
* @readonly
* @type {(RuntimeStyleInfo | BindingInfo)}
* @memberof XamGridColumnComponent
*/
@Input()
get headerStyle(): RuntimeStyleInfo | BindingInfo {
return this.modelProxy.HeaderStyle;
}
set headerStyle(value: RuntimeStyleInfo | BindingInfo) {
/* istanbul ignore else */
if (
!this.checkForStaticResourceReference(
XamGridColumnModel.HeaderStyleProperty,
value
)
) {
this.modelProxy.HeaderStyle = value as RuntimeStyleInfo;
}
}
/**
* Represent the content of the column header.
*
* @memberof XamGridColumnComponent
*/
@Input()
get headerText(): string | BindingInfo {
return this.modelProxy.HeaderText;
}
set headerText(value: string | BindingInfo) {
/* istanbul ignore else */
if (
!this.checkForStaticResourceReference(
XamGridColumnModel.HeaderTextProperty,
value
)
) {
this.modelProxy.HeaderText = value as string;
}
}
/**
* headerText two-way binding event emitter
*
* @type {EventEmitter<string>}
* @memberof XamGridColumnComponent
*/
@Output()
headerTextChange: EventEmitter<string> = new EventEmitter<string>();
/**
* Represent the key value.
*
* @memberof XamGridColumnComponent
*/
@Input()
get key(): string {
return this.modelProxy.Key;
}
/**
*
*
* @memberof XamGridColumnComponent
*/
set key(value: string) {
this.modelProxy.Key = value;
}
/**
* Gets/sets the editable property of the column.
*
* @type {boolean}
* @memberof XamGridColumnComponent
*/
@Input()
get editable(): boolean {
return this.modelProxy.Editable;
}
/**
* Sets the editable column property
*
* @memberof XamGridColumnComponent
*/
set editable(value: boolean) {
this.modelProxy.Editable = value;
}
/**
* Alias for the editable property
*
* @type {boolean | BindingInfo}
* @memberof XamGridColumnComponent
*/
@Input()
get isReadOnly(): boolean | BindingInfo {
return this.modelProxy.IsReadOnly;
}
/**
*
*
* @memberof XamGridColumnComponent
*/
set isReadOnly(value: boolean | BindingInfo) {
/* istanbul ignore else */
if (
!this.checkAndRegisterCompatibilityBindingColumns(
XamGridColumnModel.IsReadOnlyProperty,
value
)
) {
this.modelProxy.IsReadOnly = value as boolean;
}
}
/**
* checkAndRegisterCompatibilityBindingColumns
*
* @protected
* @param {DependencyProperty} property
* @param {*} bindingObjectCandidate
* @return {*} {boolean}
* @memberof XamGridColumnComponent
*/
protected checkAndRegisterCompatibilityBindingColumns(
property: DependencyProperty,
bindingObjectCandidate: any
): boolean {
return Utils.validateCompatibilityBindings(
property,
bindingObjectCandidate,
this.modelProxy,
this.pendingSetValuesColumns
);
}
/**
* Event emitter for two-way binding of the `isReadOnly` property.
*
* @type {EventEmitter<boolean>}
* @memberof XamGridColumnComponent
*/
@Output()
isReadOnlyChange: EventEmitter<boolean> = new EventEmitter<boolean>();
/**
* Gets/sets the header template of the column.
*
* @type {TemplateRef<any>}
* @memberof XamGridColumnComponent
*/
@Input()
get headerTemplate(): TemplateRef<any> {
return this.modelProxy.HeaderTemplate?.templateRef;
}
set headerTemplate(template: TemplateRef<any>) {
this.modelProxy.HeaderTemplate = new DataTemplate(template);
}
/**
* Gets/sets the cell template of the column.
*
* @type {TemplateRef<any>}
* @memberof XamGridColumnComponent
*/
@Input()
get itemTemplate(): TemplateRef<any> {
return (this.modelProxy as any)?.ItemTemplate?.templateRef;
}
/**
*
*
* @memberof XamGridColumnComponent
*/
set itemTemplate(template: TemplateRef<any>) {
(this.modelProxy as any).ItemTemplate = new DataTemplate(template);
}
/**
* Gets/sets the visibility of the column.
*
* @type {boolean | BindingInfo}
* @memberof XamGridColumnComponent
*/
@Input()
get visibility(): boolean | BindingInfo {
return this.modelProxy.Visibility;
}
/**
*
*
* @memberof XamGridColumnComponent
*/
set visibility(value: boolean | BindingInfo) {
/* istanbul ignore else */
if (
!this.checkForStaticResourceReference(
XamGridColumnModel.VisibilityProperty,
value
)
) {
this.modelProxy.Visibility = value as boolean;
}
}
/**
* Event emitter for two-way binding of the `visibility` property.
*
* @type {EventEmitter<boolean>}
* @memberof XamGridColumnComponent
*/
@Output()
visibilityChange: EventEmitter<boolean> = new EventEmitter<boolean>();
/**
* Gets whether the column can be filtered through the UI.
*
* @type {boolean}
* @memberof XamGridColumnComponent
*/
@Input()
get isFilterable(): boolean | BindingInfo {
return this.model.IsFilterable;
}
/**
* Sets whether the column can be filtered through the UI.
*
* @type {boolean}
* @memberof XamGridColumnComponent
*/
set isFilterable(value: boolean | BindingInfo) {
/* istanbul ignore else */
if (
!this.checkAndRegisterCompatibilityBindingColumns(
XamGridColumnModel.IsFilterableProperty,
value
)
) {
this.modelProxy.IsFilterable = value as boolean;
}
}
/**
* Gets/sets whether the column can be sorted through the UI.
*
* @readonly
* @type {boolean}
* @memberof XamGridColumnComponent
*/
@Input()
get sortable(): boolean {
return this.modelProxy.IsSortable;
}
/**
*
*
* @memberof XamGridColumnComponent
*/
set sortable(value: boolean) {
this.modelProxy.IsSortable = value;
}
/**
* Gets/sets whether the column can be grouped through the UI.
*
* @type {boolean}
* @memberof XamGridColumnComponent
*/
@Input()
get groupable(): boolean {
return this.modelProxy.IsGroupable;
}
/**
*
*
* @memberof XamGridColumnComponent
*/
set groupable(value: boolean) {
this.modelProxy.IsGroupable = value;
}
/**
* Gets/sets whether the column can be moved through the UI.
*
* @type {boolean}
* @memberof XamGridColumnComponent
*/
@Input()
get movable(): boolean {
return this.modelProxy.IsMovable;
}
/**
*
*
* @memberof XamGridColumnComponent
*/
set movable(value: boolean) {
this.modelProxy.IsMovable = value;
}
/**
* Gets/sets whether the column can be resized through the UI.
*
* @type {boolean}
* @memberof XamGridColumnComponent
*/
@Input()
get resizable(): boolean {
return this.modelProxy.IsResizable;
}
/**
*
*
* @memberof XamGridColumnComponent
*/
set resizable(value: boolean) {
this.modelProxy.IsResizable = value;
}
/**
* Gets/sets whether the column can be hidden.
*
* @type {boolean}
* @memberof XamGridColumnComponent
*/
@Input()
get hideable(): boolean {
return this.modelProxy.IsHideable;
}
/**
*
*
* @memberof XamGridColumnComponent
*/
set hideable(value: boolean) {
this.modelProxy.IsHideable = value;
}
/**
* Gets/sets whether the column should be pinned/unpinned.
*
* @type {boolean}
* @memberof XamGridColumnComponent
*/
@Input()
get isFixed(): boolean | string {
return this.modelProxy.IsFixed !== 0;
}
/**
*
*
* @memberof XamGridColumnComponent
*/
set isFixed(value: boolean | string) {
this.modelProxy.IsFixed = value ? 1 : 0;
}
/**
* Gets/sets whether the column can be pinned/unpinned.
*
* @type {boolean}
* @memberof XamGridColumnComponent
*/
@Input()
get fixable(): boolean {
return this.modelProxy.IsFixable;
}
/**
*
*
* @memberof XamGridColumnComponent
*/
set fixable(value: boolean) {
this.modelProxy.IsFixable = value;
}
/**
* Gets/sets the minimum width the column is allowed to be.
*
* @memberof XamGridColumnComponent
*/
@Input()
get minimumWidth() {
return this.modelProxy.MinimumWidth;
}
/**
*
*
* @memberof XamGridColumnComponent
*/
set minimumWidth(value) {
/* istanbul ignore else */
if (
!this.checkForStaticResourceReference(
XamGridColumnModel.MinimumWidthProperty,
value
)
) {
this.modelProxy.MinimumWidth = value;
}
}
/**
* Gets/sets the maximum width the column is allowed to be.
*
* @memberof XamGridColumnComponent
*/
@Input()
get maximumWidth() {
return this.modelProxy.MaximumWidth;
}
/**
*
*
* @memberof XamGridColumnComponent
*/
set maximumWidth(value) {
/* istanbul ignore else */
if (
!this.checkForStaticResourceReference(
XamGridColumnModel.MaximumWidthProperty,
value
)
) {
this.modelProxy.MaximumWidth = value;
}
}
/**
* Gets/sets the width of the column.
*
* @memberof XamGridColumnComponent
*/
@Input()
get width(): ColumnWidth {
return this.modelProxy.Width;
}
set width(value: ColumnWidth) {
/* istanbul ignore else */
if (
!this.checkForStaticResourceReference(
XamGridColumnModel.WidthProperty,
value
)
) {
this.modelProxy.Width = ColumnWidth.parse(value);
}
}
/**
* Gets/sets how a child element is horizontally positioned or stretched inside a parent layout slot
*
* @type {HorizontalAlignment}
* @memberof XamGridColumnComponent
*/
@Input()
get horizontalContentAlignment(): string | number {
return this.modelProxy.HorizontalContentAlignment;
}
set horizontalContentAlignment(value: string | number) {
this.modelProxy.HorizontalContentAlignment =
typeof value === 'number' ? value : HorizontalAlignment.parse(value);
}
/**
* Gets/sets how a child element is vertically positioned or stretched inside a parent layout slot
*
* @type {string | number}
* @memberof XamGridColumnComponent
*/
@Input()
get verticalContentAlignment(): string | number {
return this.modelProxy.VerticalContentAlignment;
}
set verticalContentAlignment(value: string | number) {
this.modelProxy.VerticalContentAlignment =
typeof value === 'number' ? value : VerticalAlignment.parse(value);
}
/**
* Gets/sets the header text horizontal alignment
*
* @type {HorizontalAlignment}
* @memberof XamGridColumnComponent
*/
@Input()
get headerTextHorizontalAlignment(): HorizontalAlignment {
return this.modelProxy.HeaderTextHorizontalAlignment;
}
set headerTextHorizontalAlignment(value: HorizontalAlignment) {
this.modelProxy.HeaderTextHorizontalAlignment = value;
}
/**
* Gets/sets the style for the column cells.
*
* @memberof XamGridColumnComponent
*/
@Input()
get cellStyle() {
return this.model.CellStyle;
}
set cellStyle(style) {
this.modelProxy.CellStyle = style;
}
/**
* Returns the data type of the column
*
* @readonly
* @memberof XamGridColumnComponent
*/
get dataType() {
return this.modelProxy.DataType;
}
/**
* This is a reference with the content of each column.
*
* @type {TemplateRef<any>}
* @memberof XamGridColumnComponent
*/
@ContentChild('columnContentTemplate')
columnContentTemplate: TemplateRef<any>;
/**
* Reference to the header template if any.
*
* @type {TemplateRef<any>}
* @memberof XamGridColumnComponent
*/
@ContentChild('columnHeaderTemplate')
columnHeaderTemplate: TemplateRef<any>;
/**
* Reference to the editor template if any.
*
* @type {TemplateRef<any>}
* @memberof XamGridColumnComponent
*/
@ContentChild('columnEditorTemplate')
columnEditorTemplate: TemplateRef<any>;
/**
* Reference to the footer template if any.
*
* @type {XamGridColumnFooterComponent}
* @memberof XamGridColumnComponent
*/
@ContentChild(XamGridColumnFooterComponent)
footerTemplate: XamGridColumnFooterComponent;
/**
* Model proxy
*
* @protected
* @memberof XamGridColumnComponent
*/
protected modelProxy = ModelProxy.create<XamGridColumnModel>();
/**
* Angular lifecycle hook
* Initialize the model for each column.
*
* @memberof XamGridColumnComponent
*/
ngOnInit(): void {
this.model = this.model ?? new XamGridColumnModel();
ModelProxy.copy(this.modelProxy, this.model);
this.modelProxy = this.model;
this.model.change.addHandler(this.applyResourcesOnParentChange, this);
}
/**
* Angular lifecycle hook.
* Initialize the column templates if present.
*
* @memberof XamGridColumnComponent
*/
ngAfterContentInit() {
/* istanbul ignore else */
if (this.columnHeaderTemplate != null)
this.model.HeaderTemplate = new DataTemplate(this.columnHeaderTemplate);
/* istanbul ignore else */
if (this.model instanceof XamGridTemplateColumnModel) {
/* istanbul ignore else */
if (this.columnEditorTemplate) {
this.model.EditorTemplate = new DataTemplate(this.columnEditorTemplate);
}
this.model.ItemTemplate = new DataTemplate(this.columnContentTemplate);
this.model.FooterTemplate = this.footerTemplate;
this.setupFooters();
} else if (this.model instanceof XamGridUnboundColumnModel) {
this.model.ItemTemplate = new DataTemplate(this.columnContentTemplate);
/* istanbul ignore else */
if (this.columnEditorTemplate) {
this.model.EditorTemplate = new DataTemplate(this.columnEditorTemplate);
}
}
this.setupFooters();
}
/**
* Recreates the binding context for the footers section
*
* @memberof XamGridColumnComponent
*/
setupFooters() {
/* istanbul ignore else */
if (this.footerTemplate?.control) {
this.model.CreateFooterOperand(this.footerTemplate);
}
}
/**
* Overrides the apply pending resource assignments
*
* @protected
* @param {DependencyObject} model
* @memberof BaseWrapperComponent
*/
/* istanbul ignore next */
protected applyPendingResourceAssignment(model: DependencyObject) {
const contextModel = this.getContextModel();
if (this.pendingResourceValues && contextModel) {
for (const [property, value] of this.pendingResourceValues) {
let processValue: any = null;
if (typeof value === 'object' && value.bindingPath) {
const binding = createBindingFromBindingInfo(value, contextModel);
const theBindingContext = resolveBindingContext(
binding,
contextModel
);
processValue = calculateBindingValue(
binding,
theBindingContext,
property
);
model.SetBinding(property, binding);
} else if (isResourceKeyValue(value)) {
processValue = getResourceKeyValue(value, contextModel);
} else {
processValue = value;
}
model.setValue(property, processValue);
}
} else {
super.applyPendingResourceAssignment(model);
}
this.pendingResourceValues = null;
}
/**
* Applies the resources until the parent is set
*
* @protected
* @param {*} propertyName
* @memberof XamGridColumnComponent
*/
protected applyResourcesOnParentChange(propertyName: any) {
/* istanbul ignore else */
if (propertyName === 'Parent') {
this.applyPendingResourceAssignment(this.model);
}
}
private getContextModel(): FrameworkElement {
/* istanbul ignore else */
if (this.model.Parent instanceof XamGridModel) {
return this.model.Parent;
}
return null;
}
}
/**
* Angular component for the Xam grid text column model
*
* @export
* @class XamGridTextColumnComponent
* @extends {XamGridColumnComponent}
* @implements {OnInit}
*/
@Component({
selector: 'wm-xam-grid-text-column',
providers: [
{
provide: XamGridColumnComponent,
useExisting: XamGridTextColumnComponent,
},
],
templateUrl: './xam-grid-column.component.html',
styleUrls: ['./xam-grid-column.component.css'],
})
export class XamGridTextColumnComponent
extends XamGridColumnComponent
implements OnInit
{
/**
* Gets/Sets the text footer for the current column
*
* @memberof XamGridTextColumnComponent
*/
@Input() set footerText(value: string) {
this.modelProxy.FooterText = value;
}
/**
* Gets/sets the text wrapping mode for the column.
*
* @memberof XamGridTextColumnComponent
*/
@Input()
get textWrapping() {
return this.modelProxy.TextWrapping;
}
/**
*
*
* @memberof XamGridTextColumnComponent
*/
set textWrapping(value) {
this.modelProxy.TextWrapping = value;
}
/**
* Gets/sets the format string for the cells in the column.
*
* @memberof XamGridTextColumnComponent
*/
@Input()
get formatString() {
return this.modelProxy.FormatString;
}
set formatString(value: string) {
this.modelProxy.FormatString = value;
}
/**
* The underlying data column model if provided
*
* @type {DataGridTextColumnModel}
* @memberof XamGridTextColumnComponent
*/
@Input()
model: XamGridTextColumnModel;
/**
* Model proxy
*
* @protected
* @memberof XamGridTextColumnComponent
*/
protected modelProxy = ModelProxy.create<XamGridTextColumnModel>();
/**
* * Angular lifecycle hook
* Initialize the model for each column.
*
* @memberof XamGridTextColumnComponent
*/
public ngOnInit() {
this.model = this.model ?? new XamGridTextColumnModel();
super.ngOnInit();
}
}
/**
* Angular component for the Xam grid checkbox column model
*
* @export
* @class XamGridCheckboxColumnComponent
* @extends {XamGridColumnComponent}
* @implements {OnInit}
*/
@Component({
selector: 'wm-xam-grid-checkbox-column',
providers: [
{
provide: XamGridColumnComponent,
useExisting: XamGridCheckboxColumnComponent,
},
],
templateUrl: './xam-grid-column.component.html',
styleUrls: ['./xam-grid-column.component.css'],
})
export class XamGridCheckboxColumnComponent
extends XamGridColumnComponent
implements OnInit
{
/**
* The underlying data column model if provided.
*
* @type {XamGridCheckboxColumnModel}
* @memberof XamGridCheckboxColumnComponent
*/
@Input()
model: XamGridCheckboxColumnModel;
protected modelProxy = ModelProxy.create<XamGridCheckboxColumnModel>();
/**
* * Angular lifecycle hook
* Initialize the model for each column.
*
* @memberof XamGridCheckboxColumnComponent
*/
public ngOnInit() {
this.model = this.model ?? new XamGridCheckboxColumnModel();
super.ngOnInit();
}
}
/**
* An alias for the default Xam grid column for easier transitioning
*
* @export
* @class XamGridTemplateColumnComponent
* @extends {XamGridColumnComponent}
* @implements {OnInit}
*/
@Component({
selector: 'wm-xam-grid-template-column',
providers: [
{
provide: XamGridColumnComponent,
useExisting: XamGridTemplateColumnComponent,
},
],
templateUrl: './xam-grid-column.component.html',
styleUrls: ['./xam-grid-column.component.css'],
})
export class XamGridTemplateColumnComponent
extends XamGridColumnComponent
implements OnInit
{
/**
* The underlying data column model if provided.
*
* @type {XamGridTemplateColumnModel}
* @memberof XamGridTemplateColumnComponent
*/
@Input()
model: XamGridTemplateColumnModel;
protected modelProxy = ModelProxy.create<XamGridTemplateColumnModel>();
/**
* Angular lifecyc\le hook.
* Initialize the model for each column.
*
* @memberof XamGridTemplateColumnComponent
*/
public ngOnInit() {
this.model = this.model ?? new XamGridTemplateColumnModel();
super.ngOnInit();
}
}
/**
* Alias for the Xam grid column for easier transitioning
*
* @export
* @class XamGridUnboundColumnComponent
* @extends {XamGridColumnComponent}
* @implements {OnInit}
*/
@Component({
selector: 'wm-xam-grid-unbound-column',
providers: [
{
provide: XamGridColumnComponent,
useExisting: XamGridUnboundColumnComponent,
},
],
templateUrl: './xam-grid-column.component.html',
styleUrls: ['./xam-grid-column.component.css'],
})
export class XamGridUnboundColumnComponent
extends XamGridColumnComponent
implements OnInit
{
/**
* The underlying data column model if provided.
*
* @type {XamGridUnboundColumnModel}
* @memberof XamGridUnboundColumnComponent
*/
@Input()
model: XamGridUnboundColumnModel;
protected modelProxy = ModelProxy.create<XamGridUnboundColumnModel>();
/**
* Initialize the model for each column.
*
* @memberof XamGridUnboundColumnComponent
*/
public ngOnInit() {
this.model = this.model ?? new XamGridUnboundColumnModel();
super.ngOnInit();
}
}
/**
* Column group container for other Xam grid columns.
*
* @export
* @class XamGridColumnGroupComponent
* @extends {XamGridColumnComponent}
* @implements {OnInit}
* @implements {AfterContentInit}
*/
@Component({
selector: 'wm-xam-grid-column-group',
providers: [
{
provide: XamGridColumnComponent,
useExisting: XamGridColumnGroupComponent,
},
],
template: `<ng-content></ng-content>`,
})
export class XamGridColumnGroupComponent
extends XamGridColumnComponent
implements OnInit, AfterContentInit
{
/**
* The underlying model.
*
* @type {XamGridGroupColumnModel}
* @memberof XamGridColumnGroupComponent
*/
@Input()
public model: XamGridGroupColumnModel;
/**
* Returns whether this model represents a a column group.
*
* @readonly
* @memberof XamGridColumnGroupComponent
*/
get isGroupColumn() {
return this.model.IsGroupColumn;
}
/**
* The column's children
*
* @type {QueryList<XamGridColumnComponent>}
* @memberof XamGridColumnGroupComponent
*/
@ContentChildren(XamGridColumnComponent)
children: QueryList<XamGridColumnComponent>;
protected modelProxy = ModelProxy.create<XamGridGroupColumnModel>();
/**
* Angular life-cycle hook
*
* @memberof XamGridColumnGroupComponent
*/
ngOnInit() {
this.model = this.model ?? new XamGridGroupColumnModel();
super.ngOnInit();
}
/**
* Angular life-cycle hook
*
* @memberof XamGridColumnGroupComponent
*/
ngAfterContentInit() {
this.children.forEach((child) => {
child.model.Parent = this.model;
this.model.AddColumn(child.model);
});
}
}
/**
* A No-op wrapper around the columns in the Xam grid.
* Useful when translating old code and keeping the same tree structure.
*
* @export
* @class XamGridColumnsComponent
*/
@Component({
selector: 'wm-xam-grid-columns',
template: `<ng-content></ng-content>`,
})
export class XamGridColumnsComponent {}
/**
* Mapper pipe transforming XamColumnModels alignments to CSS style properties.
*
* @export
* @class AlignmentMapPipe
* @implements {PipeTransform}
*/
@Pipe({ name: 'alignmentMap' })
export class AlignmentMapPipe implements PipeTransform {
/**
* Vertical mappings to CSS flex properties
*
* @memberof AlignmentMapPipe
*/
verticalMap = new Map([
[0, { 'align-items': 'flex-start' }],
[1, { 'align-items': 'flex-center' }],
[2, { 'align-items': 'flex-end' }],
[3, { 'align-items': 'stretch' }],
[4, { 'align-items': 'flex-center' }],
]);
/**
* Horizontal mappings to CSS flex properties
*
* @memberof AlignmentMapPipe
*/
horizontalMap = new Map([
[0, { 'justify-content': 'flex-start' }],
[1, { 'justify-content': 'center' }],
[2, { 'justify-content': 'flex-end' }],
[3, { 'justify-content': 'space-between' }],
]);
/**
* Applies the appropriate horizontal/vertical alignments for the grid cells.
*
* @param {HorizontalAlignment} horizontal
* @param {VerticalAlignment} vertical
* @return {*}
* @memberof AlignmentMapPipe
*/
transform(
horizontal: HorizontalAlignment,
vertical: VerticalAlignment,
styleInfo: RuntimeStyleInfo,
formatRules: any,
grid: any,
isCellChanged: number
) {
const styles = {
...this.horizontalMap.get(horizontal),
...this.verticalMap.get(vertical),
};
this.processColumnStyle(styleInfo, styles);
this.processFormatRules(formatRules, styles);
if (grid?.cellStyleEnabled && grid.renderedCalled) {
this.processRowCellStyleChange(styles, grid, isCellChanged);
}
return styles;
}
private processFormatRules(
formatRules: any,
styles: { 'align-items': string; 'justify-content': string }
) {
if (formatRules) {
formatRules.forEach((rule) => {
const [cssProp, cssString] = Object.entries(rule.StyleToApply);
styles[`${cssProp}`] = (
data: any,
key: string,
value: any,
index: number
) => (rule.callback(value) ? cssString : null);
});
}
}
/**
* Process the row cell style change
*
* @param {*} styles
* @param {*} grid
* @param {number} isCellChanged
* @memberof AlignmentMapPipe
*/
processRowCellStyleChange(styles: any, grid: any, isCellChanged: number) {
const styleBackground = styles['background-color'];
const styleColor = styles['color'];
const styleFontFamily = styles['font-family'];
const styleFontSize = styles['font-size'];
const styleFontStyle = styles['font-style'];
const styleFontWeight = styles['font-weight'];
const stylePadding = styles['padding'];
const style = {};
this.addStyleProperty(
'background-color',
'Background',
null,
colorToCSSColor,
style,
grid,
styleBackground
);
this.addStyleProperty(
'color',
'Foreground',
'black',
colorToCSSColor,
style,
grid,
styleColor
);
this.addStyleProperty(
'font-family',
'FontFamily',
null,
(s) => s,
style,
grid,
styleFontFamily
);
this.addStyleProperty(
'font-size',
'FontSize',
'inherit',
addingPixels,
style,
grid,
styleFontSize
);
this.addStyleProperty(
'font-style',
'FontStyle',
null,
(s) => Utils.getFontStyle(s),
style,
grid,
styleFontStyle
);
this.addStyleProperty(
'font-weight',
'FontWeight',
null,
(s) => Utils.getFontWeight(s),
style,
grid,
styleFontWeight
);
this.addStyleProperty(
'padding',
'Padding',
null,
addingPixels,
style,
grid,
stylePadding
);
Object.assign(styles, style);
}
/**
* Generates the property resolve function for the grid mechanism
*
* @private
* @param {string} styleProperty
* @param {string} modelProperty
* @param {*} defaultValue
* @param {*} strategy
* @param {*} stylesObj
* @param {*} grid
* @param {*} styleValue
* @memberof AlignmentMapPipe
*/
private addStyleProperty(
styleProperty: string,
modelProperty: string,
defaultValue: any,
strategy: any,
stylesObj: any,
grid: any,
styleValue: any
) {
stylesObj[styleProperty] = (rowData, colName, cellValue, rowIndex) => {
return this.processProperty(
grid,
rowIndex,
colName,
modelProperty,
defaultValue,
strategy,
styleValue
);
};
}
private processProperty(
grid: any,
rowIndex: any,
colName: any,
propertyName: string,
defaultValue: string,
strategy: any,
currentStyleValue: any
) {
// Process cell style
if (grid == null) {
return null;
}
const { row, cell } = grid.getCellByRowColumn(rowIndex, colName);
let value = defaultValue;
if (currentStyleValue == null) {
currentStyleValue = value;
}
if (cell?.Style != null) {
value = this.getStyleValue(cell?.Style, propertyName) ?? defaultValue;
value = value !== defaultValue ? strategy(value) : currentStyleValue;
}
// Process row style
if (value === defaultValue) {
value = this.getStyleValue(row.CellStyle, propertyName) ?? defaultValue;
value = value !== defaultValue ? strategy(value) : currentStyleValue;
}
return value;
}
private getStyleValue(obj: any, propertyName: string): any {
return obj?.Setters['internalArray'].find(
(x) => getPropertyName(x) === propertyName
)?.Value;
}
private processColumnStyle(styleInfo: RuntimeStyleInfo, styles: any) {
if (styleInfo) {
styleInfo.Setters.forEach((setter) =>
Object.assign(styles, runtimeStyleTransform(setter))
);
}
}
}
/**
* Pipe for applying text wrapping styles over text columns
*
* @export
* @class TextWrappingPipe
* @implements {PipeTransform}
*/
@Pipe({ name: 'textWrapping' })
export class TextWrappingPipe implements PipeTransform {
/**
* Apply the current text wrapping values
*
* @param {TextWrapping} value
* @return {*}
* @memberof TextWrappingPipe
*/
transform(value: TextWrapping) {
/* istanbul ignore else */
if (!value) {
return {};
}
return {
whiteSpace: value === 1 ? 'nowrap' : 'normal',
overflowWrap: 'anywhere',
fontSize: '0.8125rem',
};
}
}
/**
* Pipe for applying style information over column members
*
* @export
* @class StyleInfoPipe
* @implements {PipeTransform}
*/
@Pipe({ name: 'styleInfo' })
export class StyleInfoPipe implements PipeTransform {
/**
* Apply the current text style
*
* @param {RuntimeStyleInfo} value
* @return {*}
* @memberof StyleInfoPipe
*/
transform(value: RuntimeStyleInfo, headerTextAlignment: HorizontalAlignment) {
const styles = {};
if (value) {
value.Setters.forEach((setter) =>
Object.assign(styles, runtimeStyleTransform(setter))
);
}
if (headerTextAlignment !== null) {
const map = ['left', 'center', 'right', 'justify'];
styles['text-align'] = map[headerTextAlignment];
}
return styles;
}
}
/**
* Pipe for applying format strings over text columns
*
* @export
* @class XamFormatStringPipe
* @implements {PipeTransform}
*/
@Pipe({ name: 'xamFormatString' })
export class XamFormatStringPipe implements PipeTransform {
constructor(@Inject(LOCALE_ID) private locale: string, elem: ElementRef) {}
/**
* Generates a formatter function for the underlying columns
* based on the passed format string or ValueConverter.
*
* @param {string} [format]
* @return {*}
* @memberof XamFormatStringPipe
*/
transform(
format?: string,
converter?: IValueConverter,
columnModel?: any,
dataType?: string
) {
if (converter) {
return (value: any, rowData: any) => {
if (columnModel instanceof XamGridUnboundColumnModel) {
//Unbound columns receive the complete row as value
return converter.Convert(
rowData?.data ?? rowData,
undefined,
columnModel?.ValueConverterParameter,
undefined
);
} else {
return converter.Convert(value, undefined, undefined, undefined);
}
};
}
if (!format) {
if (dataType === 'date') {
format = '{0:G}';
} else {
return undefined;
}
}
return (value) => simpleStringFormat(format.replace(/^{}/, ''), value);
}
}
/**
* Map silverlight properties to CSS properties
*
* @protected
* @param {*} setter
* @return {*}
* @memberof AlignmentMapPipe
*/
export function runtimeStyleTransform(setter: any): Record<string, unknown> {
// eslint-disable-next-line
const Property = getPropertyName(setter);
const Value = setter.Value;
// eslint-disable-next-line
switch (Property) {
case 'Foreground':
return { color: smColorToCssColor(Value.Color) };
case 'Background':
return { background: smColorToCssColor(Value.Color) };
case 'BorderThickness':
return { 'border-width': Value.toString() };
case 'BorderBrush':
return { 'border-color': smColorToCssColor(Value.Color) };
case 'FontSize':
return { 'font-size': `${Value}px` };
case 'FontStyle':
return { 'font-style': Utils.getFontStyle(Value) };
case 'FontWeight':
return { 'font-weight': Utils.getFontWeight(Value) };
case 'FontFamily':
return { 'font-family': Value?.toString() };
case 'VerticalContentAlignment':
return { 'align-self': Utils.getVerticalContentAlignment(Value) };
case 'HorizontalContentAlignment':
return { 'justify-self': Utils.getHorizontalContentAlignment(Value) };
default:
// eslint-disable-next-line
return { [Property]: Value };
}
}
/**
* Gets the property name from the setter
*
* @param {*} setter
* @returns {string}
*/
function getPropertyName(setter: any): string {
return typeof setter.Property === 'object'
? setter.Property?.name
: setter.Property;
}
/**
* Adding pixels to value function
*
* @param {string} value
* @returns {string}
*/
function addingPixels(value: string): string {
return `${value}px`;
}
/**
* Color to css color function
*
* @param {*} value
* @returns {string}
*/
export function colorToCSSColor(value: any): string {
return smColorToCssColor(value.Color);
}