mirror of https://github.com/abpframework/abp.git
12 changed files with 267 additions and 270 deletions
@ -1,5 +0,0 @@ |
|||
<p>extensible-personal-settings works!</p> |
|||
|
|||
<form [formGroup]="form" (ngSubmit)="save()" validateOnSubmit> |
|||
<abp-extensible-form [selectedRecord]="selected"></abp-extensible-form> |
|||
</form> |
|||
@ -1,24 +0,0 @@ |
|||
import { ComponentFixture, TestBed } from '@angular/core/testing'; |
|||
|
|||
import { ExtensiblePersonalSettingsComponent } from './extensible-personal-settings.component'; |
|||
|
|||
describe('ExtensiblePersonalSettingsComponent', () => { |
|||
let component: ExtensiblePersonalSettingsComponent; |
|||
let fixture: ComponentFixture<ExtensiblePersonalSettingsComponent>; |
|||
|
|||
beforeEach(async () => { |
|||
await TestBed.configureTestingModule({ |
|||
declarations: [ExtensiblePersonalSettingsComponent], |
|||
}).compileComponents(); |
|||
}); |
|||
|
|||
beforeEach(() => { |
|||
fixture = TestBed.createComponent(ExtensiblePersonalSettingsComponent); |
|||
component = fixture.componentInstance; |
|||
fixture.detectChanges(); |
|||
}); |
|||
|
|||
it('should create', () => { |
|||
expect(component).toBeTruthy(); |
|||
}); |
|||
}); |
|||
@ -1,42 +0,0 @@ |
|||
import {Component, Injector, OnInit} from '@angular/core'; |
|||
import {EXTENSIONS_IDENTIFIER, FormPropData, generateFormFromProps} from "@abp/ng.theme.shared/extensions"; |
|||
import { eAccountComponents } from '../../enums/components'; |
|||
import {FormBuilder, FormGroup} from "@angular/forms"; |
|||
import {ProfileService} from "@abp/ng.account.core/proxy"; |
|||
|
|||
@Component({ |
|||
selector: 'abp-extensible-personal-settings', |
|||
templateUrl: './extensible-personal-settings.component.html', |
|||
styleUrls: ['./extensible-personal-settings.component.scss'], |
|||
providers:[ |
|||
{ |
|||
provide: EXTENSIONS_IDENTIFIER, |
|||
useValue: eAccountComponents.PersonalSettings, |
|||
}, |
|||
] |
|||
}) |
|||
export class ExtensiblePersonalSettingsComponent implements OnInit { |
|||
selected = {a: 1};// hacky for triggering 'edit' mode of extensible-form
|
|||
|
|||
form: FormGroup; |
|||
|
|||
constructor( |
|||
private profileService: ProfileService, |
|||
protected fb: FormBuilder, |
|||
protected injector: Injector, |
|||
) {} |
|||
|
|||
|
|||
buildForm() { |
|||
const data = new FormPropData(this.injector, this.selected); |
|||
this.form = generateFormFromProps(data); |
|||
} |
|||
|
|||
ngOnInit(): void { |
|||
this.buildForm() |
|||
} |
|||
|
|||
save() { |
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
import {Component, Inject} from '@angular/core'; |
|||
import {FORM_PROP_DATA_STREAM, FormProp} from "@abp/ng.theme.shared/extensions"; |
|||
import {ControlContainer, FormGroup, FormGroupDirective} from "@angular/forms"; |
|||
|
|||
@Component({ |
|||
selector: 'abp-half-row', |
|||
template: ` |
|||
<div class="col col-md-6"> |
|||
<div class="mb-3 form-group" > |
|||
<label for="surname" class="form-label">{{ |
|||
displayName | abpLocalization |
|||
}} |
|||
{{name}} |
|||
</label> |
|||
<input type="text" [attr.id]="id" class="form-control" [attr.name]="name" [formControlName]="name"/> |
|||
</div> |
|||
</div>`,
|
|||
styles: [], |
|||
viewProviders: [{ provide: ControlContainer, useExisting: FormGroupDirective }] |
|||
|
|||
}) |
|||
export class HalfRowComponent { |
|||
public displayName: string; |
|||
public name: string; |
|||
public id: string; |
|||
public formGroup: FormGroup |
|||
|
|||
constructor(@Inject(FORM_PROP_DATA_STREAM) private propData: FormProp) { |
|||
this.displayName = propData.displayName |
|||
this.name = propData.name |
|||
this.id = propData.id |
|||
} |
|||
} |
|||
@ -0,0 +1,30 @@ |
|||
import { Component } from '@angular/core'; |
|||
import {ControlContainer, FormGroupDirective} from "@angular/forms"; |
|||
|
|||
@Component({ |
|||
selector: 'abp-name-surname', |
|||
template: `<div class="row">
|
|||
<div class="col col-md-6"> |
|||
<div class="mb-3 form-group"> |
|||
<label for="name" class="form-label">{{ |
|||
'AbpIdentity::DisplayName:Name' | abpLocalization |
|||
}}</label |
|||
><input type="text" id="name" class="form-control" formControlName="name" /> |
|||
</div> |
|||
</div> |
|||
<div class="col col-md-6"> |
|||
<div class="mb-3 form-group"> |
|||
<label for="surname" class="form-label">{{ |
|||
'AbpIdentity::DisplayName:Surname' | abpLocalization |
|||
}}</label |
|||
><input type="text" id="surname" class="form-control" formControlName="surname" /> |
|||
</div> |
|||
</div> |
|||
</div>`,
|
|||
styles: [], |
|||
viewProviders: [{ provide: ControlContainer, useExisting: FormGroupDirective }] |
|||
|
|||
}) |
|||
export class NameSurnameComponent { |
|||
constructor() {} |
|||
} |
|||
@ -1,15 +1,45 @@ |
|||
import {ePropType, FormProp} from "@abp/ng.theme.shared/extensions"; |
|||
import {UpdateProfileDto} from "@abp/ng.account.core/proxy"; |
|||
import {Validators} from "@angular/forms"; |
|||
import {HelloComponent} from "../components/hello/hello.component"; |
|||
import {NameSurnameComponent} from "../components/personal-settings/name-surname/name-surname.component"; |
|||
|
|||
const { maxLength, required, email } = Validators; |
|||
export const DEFAULT_PERSONAL_SETTINGS_UPDATE_FORM_PROPS = FormProp.createMany<UpdateProfileDto>([ |
|||
{ |
|||
type: ePropType.String, |
|||
name: 'userName', |
|||
displayName: 'Account::UserName', |
|||
id: 'user-name', |
|||
validators: () => [Validators.required, Validators.maxLength(256)], |
|||
template: HelloComponent |
|||
displayName: 'AbpIdentity::DisplayName:UserName', |
|||
id: 'username', |
|||
validators: () => [required,maxLength(256)], |
|||
}, |
|||
{ |
|||
type: ePropType.String, |
|||
name: 'name', |
|||
displayName: 'AbpIdentity::DisplayName:Name', |
|||
id: 'name', |
|||
validators: () => [maxLength(64),required], |
|||
template:NameSurnameComponent |
|||
}, |
|||
{ |
|||
type: ePropType.String, |
|||
name: 'surname', |
|||
displayName: 'AbpIdentity::DisplayName:Surname', |
|||
id: 'surname', |
|||
validators: () => [maxLength(64),required], |
|||
visible:() => false |
|||
}, |
|||
{ |
|||
type: ePropType.String, |
|||
name: 'email', |
|||
displayName: 'AbpIdentity::DisplayName:Email', |
|||
id: 'email-address', |
|||
validators: () => [required, email, maxLength(256)], |
|||
}, |
|||
{ |
|||
type: ePropType.String, |
|||
name: 'phoneNumber', |
|||
displayName: 'AbpIdentity::DisplayName:PhoneNumber', |
|||
id: 'phone-number', |
|||
validators: () => [maxLength(16)], |
|||
}, |
|||
]) |
|||
|
|||
@ -1,148 +1,153 @@ |
|||
<div |
|||
class="mb-3 form-group" |
|||
*abpPermission="prop.permission; runChangeDetection: false" |
|||
[ngSwitch]="getComponent(prop)" |
|||
> |
|||
<ng-container [ngSwitch]="getComponent(prop)" |
|||
*abpPermission="prop.permission; runChangeDetection: false"> |
|||
|
|||
<ng-template ngSwitchCase="template"> |
|||
<ng-container *ngComponentOutlet="prop.template;injector:injectorForCustomComponent" > |
|||
<ng-container |
|||
[formControlName]="prop.name" |
|||
*ngComponentOutlet="prop.template;injector:injectorForCustomComponent"> |
|||
</ng-container> |
|||
</ng-template> |
|||
|
|||
<ng-template ngSwitchCase="input"> |
|||
<ng-template [ngTemplateOutlet]="label"></ng-template> |
|||
<input |
|||
#field |
|||
[id]="prop.id" |
|||
[formControlName]="prop.name" |
|||
[autocomplete]="prop.autocomplete" |
|||
[type]="getType(prop)" |
|||
[abpDisabled]="disabled" |
|||
[readonly]="readonly" |
|||
class="form-control" |
|||
/> |
|||
</ng-template> |
|||
|
|||
<ng-template ngSwitchCase="hidden"> |
|||
<input [formControlName]="prop.name" type="hidden" /> |
|||
</ng-template> |
|||
<div |
|||
class="mb-3 form-group" |
|||
> |
|||
|
|||
<ng-template ngSwitchCase="checkbox"> |
|||
<div class="form-check" validationTarget> |
|||
<ng-template ngSwitchCase="input"> |
|||
<ng-template [ngTemplateOutlet]="label"></ng-template> |
|||
<input |
|||
#field |
|||
[id]="prop.id" |
|||
[formControlName]="prop.name" |
|||
[autocomplete]="prop.autocomplete" |
|||
[type]="getType(prop)" |
|||
[abpDisabled]="disabled" |
|||
type="checkbox" |
|||
class="form-check-input" |
|||
[readonly]="readonly" |
|||
class="form-control" |
|||
/> |
|||
<ng-template |
|||
[ngTemplateOutlet]="label" |
|||
[ngTemplateOutletContext]="{ $implicit: 'form-check-label' }" |
|||
></ng-template> |
|||
</div> |
|||
</ng-template> |
|||
</ng-template> |
|||
|
|||
<ng-template ngSwitchCase="select"> |
|||
<ng-template [ngTemplateOutlet]="label"></ng-template> |
|||
<select |
|||
#field |
|||
[id]="prop.id" |
|||
[formControlName]="prop.name" |
|||
[abpDisabled]="disabled" |
|||
class="form-select form-control" |
|||
> |
|||
<option |
|||
*ngFor="let option of options$ | async; trackBy: track.by('value')" |
|||
[ngValue]="option.value" |
|||
> |
|||
{{ option.key }} |
|||
</option> |
|||
</select> |
|||
</ng-template> |
|||
<ng-template ngSwitchCase="hidden"> |
|||
<input [formControlName]="prop.name" type="hidden"/> |
|||
</ng-template> |
|||
|
|||
<ng-template ngSwitchCase="multiselect"> |
|||
<ng-template [ngTemplateOutlet]="label"></ng-template> |
|||
<select |
|||
#field |
|||
[id]="prop.id" |
|||
[formControlName]="prop.name" |
|||
[abpDisabled]="disabled" |
|||
multiple="multiple" |
|||
class="form-select form-control" |
|||
> |
|||
<option |
|||
*ngFor="let option of options$ | async; trackBy: track.by('value')" |
|||
[ngValue]="option.value" |
|||
<ng-template ngSwitchCase="checkbox"> |
|||
<div class="form-check" validationTarget> |
|||
<input |
|||
#field |
|||
[id]="prop.id" |
|||
[formControlName]="prop.name" |
|||
[abpDisabled]="disabled" |
|||
type="checkbox" |
|||
class="form-check-input" |
|||
/> |
|||
<ng-template |
|||
[ngTemplateOutlet]="label" |
|||
[ngTemplateOutletContext]="{ $implicit: 'form-check-label' }" |
|||
></ng-template> |
|||
</div> |
|||
</ng-template> |
|||
|
|||
<ng-template ngSwitchCase="select"> |
|||
<ng-template [ngTemplateOutlet]="label"></ng-template> |
|||
<select |
|||
#field |
|||
[id]="prop.id" |
|||
[formControlName]="prop.name" |
|||
[abpDisabled]="disabled" |
|||
class="form-select form-control" |
|||
> |
|||
{{ option.key }} |
|||
</option> |
|||
</select> |
|||
</ng-template> |
|||
<option |
|||
*ngFor="let option of options$ | async; trackBy: track.by('value')" |
|||
[ngValue]="option.value" |
|||
> |
|||
{{ option.key }} |
|||
</option> |
|||
</select> |
|||
</ng-template> |
|||
|
|||
<ng-template ngSwitchCase="typeahead"> |
|||
<ng-template [ngTemplateOutlet]="label"></ng-template> |
|||
<div #typeahead class="position-relative" validationStyle validationTarget> |
|||
<input |
|||
<ng-template ngSwitchCase="multiselect"> |
|||
<ng-template [ngTemplateOutlet]="label"></ng-template> |
|||
<select |
|||
#field |
|||
[id]="prop.id" |
|||
[autocomplete]="prop.autocomplete" |
|||
[formControlName]="prop.name" |
|||
[abpDisabled]="disabled" |
|||
[ngbTypeahead]="search" |
|||
[editable]="false" |
|||
[inputFormatter]="typeaheadFormatter" |
|||
[resultFormatter]="typeaheadFormatter" |
|||
[ngModelOptions]="{ standalone: true }" |
|||
[(ngModel)]="typeaheadModel" |
|||
(selectItem)="setTypeaheadValue($event.item)" |
|||
(blur)="setTypeaheadValue(typeaheadModel)" |
|||
[class.is-invalid]="typeahead.classList.contains('is-invalid')" |
|||
multiple="multiple" |
|||
class="form-select form-control" |
|||
> |
|||
<option |
|||
*ngFor="let option of options$ | async; trackBy: track.by('value')" |
|||
[ngValue]="option.value" |
|||
> |
|||
{{ option.key }} |
|||
</option> |
|||
</select> |
|||
</ng-template> |
|||
|
|||
<ng-template ngSwitchCase="typeahead"> |
|||
<ng-template [ngTemplateOutlet]="label"></ng-template> |
|||
<div #typeahead class="position-relative" validationStyle validationTarget> |
|||
<input |
|||
#field |
|||
[id]="prop.id" |
|||
[autocomplete]="prop.autocomplete" |
|||
[abpDisabled]="disabled" |
|||
[ngbTypeahead]="search" |
|||
[editable]="false" |
|||
[inputFormatter]="typeaheadFormatter" |
|||
[resultFormatter]="typeaheadFormatter" |
|||
[ngModelOptions]="{ standalone: true }" |
|||
[(ngModel)]="typeaheadModel" |
|||
(selectItem)="setTypeaheadValue($event.item)" |
|||
(blur)="setTypeaheadValue(typeaheadModel)" |
|||
[class.is-invalid]="typeahead.classList.contains('is-invalid')" |
|||
class="form-control" |
|||
/> |
|||
<input [formControlName]="prop.name" type="hidden"/> |
|||
</div> |
|||
</ng-template> |
|||
|
|||
<ng-template ngSwitchCase="date"> |
|||
<ng-template [ngTemplateOutlet]="label"></ng-template> |
|||
<input |
|||
[id]="prop.id" |
|||
[formControlName]="prop.name" |
|||
(click)="datepicker.open()" |
|||
(keyup.space)="datepicker.open()" |
|||
ngbDatepicker |
|||
#datepicker="ngbDatepicker" |
|||
type="text" |
|||
class="form-control" |
|||
/> |
|||
<input [formControlName]="prop.name" type="hidden" /> |
|||
</div> |
|||
</ng-template> |
|||
</ng-template> |
|||
|
|||
<ng-template ngSwitchCase="date"> |
|||
<ng-template [ngTemplateOutlet]="label"></ng-template> |
|||
<input |
|||
[id]="prop.id" |
|||
[formControlName]="prop.name" |
|||
(click)="datepicker.open()" |
|||
(keyup.space)="datepicker.open()" |
|||
ngbDatepicker |
|||
#datepicker="ngbDatepicker" |
|||
type="text" |
|||
class="form-control" |
|||
/> |
|||
</ng-template> |
|||
<ng-template ngSwitchCase="time"> |
|||
<ng-template [ngTemplateOutlet]="label"></ng-template> |
|||
<ngb-timepicker [formControlName]="prop.name"></ngb-timepicker> |
|||
</ng-template> |
|||
|
|||
<ng-template ngSwitchCase="time"> |
|||
<ng-template [ngTemplateOutlet]="label"></ng-template> |
|||
<ngb-timepicker [formControlName]="prop.name"></ngb-timepicker> |
|||
</ng-template> |
|||
<ng-template ngSwitchCase="dateTime"> |
|||
<ng-template [ngTemplateOutlet]="label"></ng-template> |
|||
<abp-date-time-picker [prop]="prop" [meridian]="meridian"></abp-date-time-picker> |
|||
</ng-template> |
|||
|
|||
<ng-template ngSwitchCase="dateTime"> |
|||
<ng-template [ngTemplateOutlet]="label"></ng-template> |
|||
<abp-date-time-picker [prop]="prop" [meridian]="meridian"></abp-date-time-picker> |
|||
</ng-template> |
|||
<ng-template ngSwitchCase="textarea"> |
|||
<ng-template [ngTemplateOutlet]="label"></ng-template> |
|||
<textarea |
|||
#field |
|||
[id]="prop.id" |
|||
[formControlName]="prop.name" |
|||
[abpDisabled]="disabled" |
|||
[readonly]="readonly" |
|||
class="form-control" |
|||
></textarea> |
|||
</ng-template> |
|||
</div> |
|||
|
|||
<ng-template ngSwitchCase="textarea"> |
|||
<ng-template [ngTemplateOutlet]="label"></ng-template> |
|||
<textarea |
|||
#field |
|||
[id]="prop.id" |
|||
[formControlName]="prop.name" |
|||
[abpDisabled]="disabled" |
|||
[readonly]="readonly" |
|||
class="form-control" |
|||
></textarea> |
|||
</ng-template> |
|||
</div> |
|||
</ng-container> |
|||
|
|||
<ng-template #label let-classes> |
|||
<label [htmlFor]="prop.id" [ngClass]="classes || 'form-label'" |
|||
>{{ prop.displayName | abpLocalization }} {{ asterisk }}</label |
|||
>{{ prop.displayName | abpLocalization }} {{ asterisk }}</label |
|||
> |
|||
</ng-template> |
|||
|
|||
Loading…
Reference in new issue