mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
[AAE-20769] Fix precision for incoming values in bigdecimal field (#9434)
* [AAE-20769] Fix precision for incoming values in bigdecimal field * CR
This commit is contained in:
@@ -38,7 +38,8 @@ import {
|
||||
checkboxWidgetFormVisibilityMock,
|
||||
dateWidgetFormVisibilityMock,
|
||||
multilineWidgetFormVisibilityMock,
|
||||
displayTextWidgetFormVisibilityMock
|
||||
displayTextWidgetFormVisibilityMock,
|
||||
displayBigDecimalWidgetMock
|
||||
} from './mock/form-renderer.component.mock';
|
||||
import { FormService } from '../services/form.service';
|
||||
import { CoreTestingModule } from '../../testing';
|
||||
@@ -849,4 +850,15 @@ describe('Form Renderer Component', () => {
|
||||
expectElementToBeHidden(displayTextContainer);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Display Bigdecimal Widget', () => {
|
||||
it('should round decimal field value to correct precision', async () => {
|
||||
formRendererComponent.formDefinition = formService.parseForm(displayBigDecimalWidgetMock.formRepresentation.formDefinition);
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
const decimalInputElement = fixture.nativeElement.querySelector('#Decimal0tzu53');
|
||||
expect(decimalInputElement.value).toBeTruthy('10.12');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -15,11 +15,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Component, ViewEncapsulation, Input, OnDestroy, Injector, OnChanges } from '@angular/core';
|
||||
import { Component, ViewEncapsulation, Input, OnDestroy, Injector, OnChanges, OnInit, Inject } from '@angular/core';
|
||||
import { FormRulesManager, formRulesManagerFactory } from '../models/form-rules.model';
|
||||
import { FormModel } from './widgets/core/form.model';
|
||||
import { ContainerModel, FormFieldModel, TabModel } from './widgets';
|
||||
import { FormService } from '../services/form.service';
|
||||
import { FORM_FIELD_MODEL_RENDER_MIDDLEWARE, FormFieldModelRenderMiddleware } from './middlewares/middleware';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-form-renderer',
|
||||
@@ -31,10 +32,11 @@ import { FormService } from '../services/form.service';
|
||||
useFactory: formRulesManagerFactory,
|
||||
deps: [Injector]
|
||||
}
|
||||
|
||||
],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class FormRendererComponent<T> implements OnChanges, OnDestroy {
|
||||
export class FormRendererComponent<T> implements OnInit, OnChanges, OnDestroy {
|
||||
/** Toggle debug options. */
|
||||
@Input()
|
||||
showDebugButton: boolean = false;
|
||||
@@ -46,7 +48,16 @@ export class FormRendererComponent<T> implements OnChanges, OnDestroy {
|
||||
|
||||
fields: FormFieldModel[];
|
||||
|
||||
constructor(public formService: FormService, private formRulesManager: FormRulesManager<T>) {}
|
||||
constructor(
|
||||
public formService: FormService,
|
||||
private formRulesManager: FormRulesManager<T>,
|
||||
@Inject(FORM_FIELD_MODEL_RENDER_MIDDLEWARE)
|
||||
private middlewareServices: FormFieldModelRenderMiddleware[]
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.runMiddlewareServices();
|
||||
}
|
||||
|
||||
ngOnChanges(): void {
|
||||
this.formRulesManager.initialize(this.formDefinition);
|
||||
@@ -123,4 +134,16 @@ export class FormRendererComponent<T> implements OnChanges, OnDestroy {
|
||||
const colspan = container ? container.field.colspan : 1;
|
||||
return (100 / container.field.numberOfColumns) * colspan + '';
|
||||
}
|
||||
|
||||
private runMiddlewareServices(): void {
|
||||
const formFields = this.formDefinition.getFormFields();
|
||||
|
||||
formFields.forEach(field => {
|
||||
this.middlewareServices.forEach((middlewareService) => {
|
||||
if (middlewareService.type === field.type) {
|
||||
field = middlewareService.getParsedField(field);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,83 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2023 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { FormFieldModel, FormFieldTypes, FormModel } from '../widgets';
|
||||
import { DecimalRenderMiddlewareService } from './decimal-middleware.service';
|
||||
|
||||
describe('DecimalRenderMiddlewareService', () => {
|
||||
let decimalMiddlewareService: DecimalRenderMiddlewareService;
|
||||
let formFieldModel: FormFieldModel;
|
||||
|
||||
beforeEach(() => {
|
||||
decimalMiddlewareService = new DecimalRenderMiddlewareService();
|
||||
|
||||
const form = new FormModel();
|
||||
formFieldModel = new FormFieldModel(form, {
|
||||
type: FormFieldTypes.DECIMAL,
|
||||
id: 'id',
|
||||
precision: 3,
|
||||
value: '10.1060'
|
||||
});
|
||||
});
|
||||
|
||||
it('should return field with proper precisison', () => {
|
||||
formFieldModel.value = '10.1000000000000';
|
||||
formFieldModel.precision = 3;
|
||||
const parsedField = decimalMiddlewareService.getParsedField(formFieldModel);
|
||||
expect(parsedField.value).toBe('10.100');
|
||||
});
|
||||
|
||||
it('should round up number with correct precisison', () => {
|
||||
formFieldModel.value = '10.1039999';
|
||||
formFieldModel.precision = 3;
|
||||
const parsedField = decimalMiddlewareService.getParsedField(formFieldModel);
|
||||
expect(parsedField.value).toBe('10.104');
|
||||
});
|
||||
|
||||
it('should round up number, when removed fraction part starts with number larger or equal 5', () => {
|
||||
formFieldModel.value = '10.1035000';
|
||||
formFieldModel.precision = 3;
|
||||
const parsedField = decimalMiddlewareService.getParsedField(formFieldModel);
|
||||
expect(parsedField.value).toBe('10.104');
|
||||
});
|
||||
|
||||
it('should NOT round up number, when removed fraction part starts with number smaller than 5', () => {
|
||||
formFieldModel.value = '10.1034999';
|
||||
formFieldModel.precision = 3;
|
||||
const parsedField = decimalMiddlewareService.getParsedField(formFieldModel);
|
||||
expect(parsedField.value).toBe('10.103');
|
||||
});
|
||||
|
||||
it('should return the same value when precision is correct', () => {
|
||||
formFieldModel.value = '10.123';
|
||||
formFieldModel.precision = 3;
|
||||
const parsedField = decimalMiddlewareService.getParsedField(formFieldModel);
|
||||
expect(parsedField.value).toBe('10.123');
|
||||
});
|
||||
|
||||
it('should work when value is not defined', () => {
|
||||
formFieldModel.value = null;
|
||||
const parsedField = decimalMiddlewareService.getParsedField(formFieldModel);
|
||||
expect(parsedField.value).toBe(null);
|
||||
});
|
||||
|
||||
it('should work when value is number', () => {
|
||||
formFieldModel.value = 3.333;
|
||||
const parsedField = decimalMiddlewareService.getParsedField(formFieldModel);
|
||||
expect(parsedField.value).toBe(3.333);
|
||||
});
|
||||
});
|
@@ -0,0 +1,53 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2023 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { FormFieldModelRenderMiddleware } from './middleware';
|
||||
import { FormFieldModel, FormFieldTypes } from '../widgets';
|
||||
|
||||
@Injectable()
|
||||
export class DecimalRenderMiddlewareService implements FormFieldModelRenderMiddleware {
|
||||
type = FormFieldTypes.DECIMAL;
|
||||
|
||||
getParsedField(field: FormFieldModel): FormFieldModel {
|
||||
const allowedMaxPrecision = field.precision;
|
||||
const value = field.value;
|
||||
|
||||
field.value = this.forceMaxPrecisionIfNeeded(value, allowedMaxPrecision);
|
||||
|
||||
return field;
|
||||
}
|
||||
|
||||
private forceMaxPrecisionIfNeeded(value: string | number, allowedMaxPrecision): string | number {
|
||||
let numberOfDecimalDigits = 0;
|
||||
const stringValue = typeof value === 'string' ? value : `${value}`;
|
||||
const numberChunks = stringValue.split('.');
|
||||
|
||||
if (numberChunks.length === 2) {
|
||||
numberOfDecimalDigits = numberChunks[1].length;
|
||||
}
|
||||
|
||||
if (numberOfDecimalDigits > allowedMaxPrecision) {
|
||||
const valueWithCorrectPrecision = parseFloat(value.toString())
|
||||
.toFixed(allowedMaxPrecision);
|
||||
|
||||
return valueWithCorrectPrecision;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
};
|
26
lib/core/src/lib/form/components/middlewares/middleware.ts
Normal file
26
lib/core/src/lib/form/components/middlewares/middleware.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2023 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { InjectionToken } from '@angular/core';
|
||||
import { FormFieldModel } from '../../components/widgets';
|
||||
|
||||
export interface FormFieldModelRenderMiddleware {
|
||||
type: string;
|
||||
getParsedField(field: FormFieldModel): FormFieldModel;
|
||||
}
|
||||
|
||||
export const FORM_FIELD_MODEL_RENDER_MIDDLEWARE = new InjectionToken('RENDER_FORM_FIELD_MODEL_MIDDLEWARE');
|
@@ -15,6 +15,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { FormFieldTypes } from '../widgets';
|
||||
|
||||
export const formDisplayValueVisibility = {
|
||||
formRepresentation: {
|
||||
id: 'form-3175b074-53c6-4b5b-92df-246b62108db3',
|
||||
@@ -2086,3 +2088,50 @@ export const displayTextWidgetFormVisibilityMock = {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const displayBigDecimalWidgetMock = {
|
||||
formRepresentation: {
|
||||
id: 'form-098756a5-2222-4c3a-1111-81dabc9a88b6',
|
||||
name: 'displayBigdecimalForm',
|
||||
description: '',
|
||||
version: 0,
|
||||
standAlone: true,
|
||||
formDefinition: {
|
||||
tabs: [],
|
||||
fields: [
|
||||
{
|
||||
id: '45269202-5f2a-438e-b14c-fe13eb4b2aa1',
|
||||
name: 'Label',
|
||||
type: 'container',
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
{
|
||||
id: 'Decimal0tzu53',
|
||||
name: 'Bigdecimal',
|
||||
type: FormFieldTypes.DECIMAL,
|
||||
required: false,
|
||||
colspan: 1,
|
||||
placeholder: null,
|
||||
minLength: 0,
|
||||
maxLength: 0,
|
||||
regexPattern: null,
|
||||
visibilityCondition: null,
|
||||
precision: 2,
|
||||
value: '10.12345678',
|
||||
params: {
|
||||
existingColspan: 1,
|
||||
maxColspan: 2
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
outcomes: [],
|
||||
metadata: {},
|
||||
variables: []
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@@ -23,7 +23,6 @@
|
||||
pattern="-?[0-9]*(\.[0-9]*)?"
|
||||
[id]="field.id"
|
||||
[required]="isRequired()"
|
||||
[value]="displayValue"
|
||||
[(ngModel)]="field.value"
|
||||
(ngModelChange)="onFieldChanged(field)"
|
||||
[disabled]="field.readOnly"
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
|
||||
import { Component, ViewEncapsulation } from '@angular/core';
|
||||
import { FormService } from '../../../services/form.service';
|
||||
import { WidgetComponent } from '../widget.component';
|
||||
|
||||
@@ -36,14 +36,8 @@ import { WidgetComponent } from '../widget.component';
|
||||
},
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class DecimalWidgetComponent extends WidgetComponent implements OnInit {
|
||||
displayValue: number;
|
||||
|
||||
export class DecimalWidgetComponent extends WidgetComponent {
|
||||
constructor(public formService: FormService) {
|
||||
super(formService);
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.displayValue = this.field.value;
|
||||
}
|
||||
}
|
||||
|
@@ -37,6 +37,8 @@ import { EditJsonDialogModule } from '../dialogs/edit-json/edit-json.dialog.modu
|
||||
import { A11yModule } from '@angular/cdk/a11y';
|
||||
import { ViewerModule } from '../viewer/viewer.module';
|
||||
import { InplaceFormInputComponent } from './components/inplace-form-input/inplace-form-input.component';
|
||||
import { FORM_FIELD_MODEL_RENDER_MIDDLEWARE } from './components/middlewares/middleware';
|
||||
import { DecimalRenderMiddlewareService } from './components/middlewares/decimal-middleware.service';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
@@ -70,7 +72,12 @@ import { InplaceFormInputComponent } from './components/inplace-form-input/inpla
|
||||
...WIDGET_DIRECTIVES,
|
||||
InplaceFormInputComponent,
|
||||
WidgetComponent
|
||||
]
|
||||
],
|
||||
providers: [{
|
||||
provide: FORM_FIELD_MODEL_RENDER_MIDDLEWARE,
|
||||
useClass: DecimalRenderMiddlewareService,
|
||||
multi: true
|
||||
}]
|
||||
})
|
||||
export class FormBaseModule {
|
||||
}
|
||||
|
Reference in New Issue
Block a user