mirror of https://github.com/abpframework/abp.git
118 changed files with 789 additions and 739 deletions
@ -1,6 +1,6 @@ |
|||
{ |
|||
"sdk": { |
|||
"version": "8.0.100-rc.2.23502.2", |
|||
"version": "8.0.100", |
|||
"rollForward": "latestFeature" |
|||
} |
|||
} |
|||
|
|||
@ -1,73 +1,76 @@ |
|||
import { TrackByService } from '@abp/ng.core'; |
|||
import {TrackByService} from '@abp/ng.core'; |
|||
import { |
|||
ChangeDetectionStrategy, |
|||
ChangeDetectorRef, |
|||
Component, |
|||
Inject, |
|||
Input, |
|||
Optional, |
|||
QueryList, |
|||
SkipSelf, |
|||
ViewChildren, |
|||
ChangeDetectionStrategy, |
|||
ChangeDetectorRef, |
|||
Component, inject, |
|||
Input, |
|||
Optional, |
|||
QueryList, |
|||
SkipSelf, |
|||
ViewChildren, |
|||
} from '@angular/core'; |
|||
import { ControlContainer, UntypedFormGroup } from '@angular/forms'; |
|||
import { EXTRA_PROPERTIES_KEY } from '../../constants/extra-properties'; |
|||
import { FormPropList, GroupedFormPropList } from '../../models/form-props'; |
|||
import { ExtensionsService } from '../../services/extensions.service'; |
|||
import { EXTENSIONS_IDENTIFIER } from '../../tokens/extensions.token'; |
|||
import { selfFactory } from '../../utils/factory.util'; |
|||
import { ExtensibleFormPropComponent } from './extensible-form-prop.component'; |
|||
import {ControlContainer, ReactiveFormsModule, UntypedFormGroup} from '@angular/forms'; |
|||
import {EXTRA_PROPERTIES_KEY} from '../../constants/extra-properties'; |
|||
import {FormPropList, GroupedFormPropList} from '../../models/form-props'; |
|||
import {ExtensionsService} from '../../services/extensions.service'; |
|||
import {EXTENSIONS_IDENTIFIER} from '../../tokens/extensions.token'; |
|||
import {selfFactory} from '../../utils/factory.util'; |
|||
import {ExtensibleFormPropComponent} from './extensible-form-prop.component'; |
|||
import {CommonModule} from "@angular/common"; |
|||
import {PropDataDirective} from "../../directives/prop-data.directive"; |
|||
|
|||
@Component({ |
|||
exportAs: 'abpExtensibleForm', |
|||
selector: 'abp-extensible-form', |
|||
templateUrl: './extensible-form.component.html', |
|||
changeDetection: ChangeDetectionStrategy.OnPush, |
|||
viewProviders: [ |
|||
{ |
|||
provide: ControlContainer, |
|||
useFactory: selfFactory, |
|||
deps: [[new Optional(), new SkipSelf(), ControlContainer]], |
|||
}, |
|||
], |
|||
exportAs: 'abpExtensibleForm', |
|||
selector: 'abp-extensible-form', |
|||
templateUrl: './extensible-form.component.html', |
|||
standalone:true, |
|||
imports:[CommonModule, PropDataDirective,ReactiveFormsModule,ExtensibleFormPropComponent], |
|||
changeDetection: ChangeDetectionStrategy.OnPush, |
|||
viewProviders: [ |
|||
{ |
|||
provide: ControlContainer, |
|||
useFactory: selfFactory, |
|||
deps: [[new Optional(), new SkipSelf(), ControlContainer]], |
|||
}, |
|||
], |
|||
}) |
|||
export class ExtensibleFormComponent<R = any> { |
|||
@ViewChildren(ExtensibleFormPropComponent) |
|||
formProps!: QueryList<ExtensibleFormPropComponent>; |
|||
|
|||
@Input() |
|||
set selectedRecord(record: R) { |
|||
const type = !record || JSON.stringify(record) === '{}' ? 'create' : 'edit'; |
|||
const propList = this.extensions[`${type}FormProps`].get(this.identifier).props; |
|||
this.groupedPropList = this.createGroupedList(propList); |
|||
this.record = record; |
|||
} |
|||
@ViewChildren(ExtensibleFormPropComponent) |
|||
formProps!: QueryList<ExtensibleFormPropComponent>; |
|||
|
|||
extraPropertiesKey = EXTRA_PROPERTIES_KEY; |
|||
groupedPropList!: GroupedFormPropList; |
|||
record!: R; |
|||
@Input() |
|||
set selectedRecord(record: R) { |
|||
const type = !record || JSON.stringify(record) === '{}' ? 'create' : 'edit'; |
|||
const propList = this.extensions[`${type}FormProps`].get(this.identifier).props; |
|||
this.groupedPropList = this.createGroupedList(propList); |
|||
this.record = record; |
|||
} |
|||
|
|||
createGroupedList(propList: FormPropList<R>) { |
|||
const groupedFormPropList = new GroupedFormPropList(); |
|||
propList.forEach(item => { |
|||
groupedFormPropList.addItem(item.value); |
|||
}); |
|||
return groupedFormPropList; |
|||
} |
|||
extraPropertiesKey = EXTRA_PROPERTIES_KEY; |
|||
groupedPropList!: GroupedFormPropList; |
|||
record!: R; |
|||
|
|||
get form(): UntypedFormGroup { |
|||
return (this.container ? this.container.control : { controls: {} }) as UntypedFormGroup; |
|||
} |
|||
public readonly cdRef = inject(ChangeDetectorRef) |
|||
public readonly track = inject(TrackByService) |
|||
private container = inject(ControlContainer) |
|||
private extensions = inject(ExtensionsService); |
|||
private identifier = inject(EXTENSIONS_IDENTIFIER) |
|||
|
|||
get extraProperties(): UntypedFormGroup { |
|||
return (this.form.controls.extraProperties || { controls: {} }) as UntypedFormGroup; |
|||
} |
|||
createGroupedList(propList: FormPropList<R>) { |
|||
const groupedFormPropList = new GroupedFormPropList(); |
|||
propList.forEach(item => { |
|||
groupedFormPropList.addItem(item.value); |
|||
}); |
|||
return groupedFormPropList; |
|||
} |
|||
|
|||
get form(): UntypedFormGroup { |
|||
return (this.container ? this.container.control : {controls: {}}) as UntypedFormGroup; |
|||
} |
|||
|
|||
get extraProperties(): UntypedFormGroup { |
|||
return (this.form.controls.extraProperties || {controls: {}}) as UntypedFormGroup; |
|||
} |
|||
|
|||
constructor( |
|||
public readonly cdRef: ChangeDetectorRef, |
|||
public readonly track: TrackByService, |
|||
private container: ControlContainer, |
|||
private extensions: ExtensionsService, |
|||
@Inject(EXTENSIONS_IDENTIFIER) private identifier: string, |
|||
) {} |
|||
} |
|||
|
|||
@ -0,0 +1,77 @@ |
|||
import { inject, Injectable } from '@angular/core'; |
|||
import { ValidatorFn, Validators } from '@angular/forms'; |
|||
import { AbpValidators, ConfigStateService } from '@abp/ng.core'; |
|||
import { map } from 'rxjs/operators'; |
|||
import { FormProp } from '../models/form-props'; |
|||
import { ePropType } from '../enums/props.enum'; |
|||
|
|||
@Injectable() |
|||
export class ExtensibleFormPropService { |
|||
readonly #configStateService = inject(ConfigStateService); |
|||
|
|||
meridian$ = this.#configStateService |
|||
.getDeep$('localization.currentCulture.dateTimeFormat.shortTimePattern') |
|||
.pipe(map((shortTimePattern: string | undefined) => (shortTimePattern || '').includes('tt'))); |
|||
|
|||
isRequired(validator: ValidatorFn) { |
|||
return ( |
|||
validator === Validators.required || |
|||
validator === AbpValidators.required || |
|||
validator.name === 'required' |
|||
); |
|||
} |
|||
|
|||
getComponent(prop: FormProp) { |
|||
if (prop.template) { |
|||
return 'template'; |
|||
} |
|||
switch (prop.type) { |
|||
case ePropType.Boolean: |
|||
return 'checkbox'; |
|||
case ePropType.Date: |
|||
return 'date'; |
|||
case ePropType.DateTime: |
|||
return 'dateTime'; |
|||
case ePropType.Hidden: |
|||
return 'hidden'; |
|||
case ePropType.MultiSelect: |
|||
return 'multiselect'; |
|||
case ePropType.Text: |
|||
return 'textarea'; |
|||
case ePropType.Time: |
|||
return 'time'; |
|||
case ePropType.Typeahead: |
|||
return 'typeahead'; |
|||
case ePropType.PasswordInputGroup: |
|||
return 'passwordinputgroup'; |
|||
default: |
|||
return prop.options ? 'select' : 'input'; |
|||
} |
|||
} |
|||
|
|||
getType(prop: FormProp) { |
|||
switch (prop.type) { |
|||
case ePropType.Date: |
|||
case ePropType.String: |
|||
return 'text'; |
|||
case ePropType.Boolean: |
|||
return 'checkbox'; |
|||
case ePropType.Number: |
|||
return 'number'; |
|||
case ePropType.Email: |
|||
return 'email'; |
|||
case ePropType.Password: |
|||
return 'password'; |
|||
case ePropType.PasswordInputGroup: |
|||
return 'passwordinputgroup'; |
|||
default: |
|||
return 'hidden'; |
|||
} |
|||
} |
|||
|
|||
calcAsterisks(validators: ValidatorFn[]) { |
|||
if (!validators) return ''; |
|||
const required = validators.find(v => this.isRequired(v)); |
|||
return required ? '*' : ''; |
|||
} |
|||
} |
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue