|
|
|
@ -1,92 +1,149 @@ |
|
|
|
<ng-container *abpPermission="prop().permission; runChangeDetection: false"> |
|
|
|
@switch (getComponent(prop())) { |
|
|
|
@case ('template') { |
|
|
|
<ng-container *ngComponentOutlet="prop().template; injector: injectorForCustomComponent" /> |
|
|
|
} |
|
|
|
@case ('template') { |
|
|
|
<ng-container *ngComponentOutlet="prop().template; injector: injectorForCustomComponent" /> |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
<div [class]="containerClassName" class="mb-2"> |
|
|
|
@switch (getComponent(prop())) { |
|
|
|
@case ('input') { |
|
|
|
<ng-template [ngTemplateOutlet]="label" /> |
|
|
|
<input #field [id]="prop().id" [formControlName]="prop().name" [autocomplete]="prop().autocomplete" [type]="getType(prop())" |
|
|
|
[abpDisabled]="disabled" [readonly]="readonly" class="form-control" /> |
|
|
|
} |
|
|
|
@case ('hidden') { |
|
|
|
<input [formControlName]="prop().name" type="hidden" /> |
|
|
|
} |
|
|
|
@case ('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' }" /> |
|
|
|
</div> |
|
|
|
} |
|
|
|
@case ('select') { |
|
|
|
<ng-template [ngTemplateOutlet]="label" /> |
|
|
|
<select #field [id]="prop().id" [formControlName]="prop().name" [abpDisabled]="disabled" |
|
|
|
class="form-select form-control"> |
|
|
|
@for (option of options$ | async; track option.value) { |
|
|
|
<option [ngValue]="option.value"> |
|
|
|
@if (prop().isExtra) { |
|
|
|
{{ '::' + option.key | abpLocalization }} |
|
|
|
} @else { |
|
|
|
{{ option.key }} |
|
|
|
} |
|
|
|
</option> |
|
|
|
@case ('input') { |
|
|
|
<ng-template [ngTemplateOutlet]="label" /> |
|
|
|
<input |
|
|
|
#field |
|
|
|
[id]="prop().id" |
|
|
|
[formControlName]="prop().name" |
|
|
|
[autocomplete]="prop().autocomplete" |
|
|
|
[type]="getType(prop())" |
|
|
|
[abpDisabled]="disabled" |
|
|
|
[readonly]="readonly" |
|
|
|
class="form-control" |
|
|
|
/> |
|
|
|
} |
|
|
|
@case ('hidden') { |
|
|
|
<input [formControlName]="prop().name" type="hidden" /> |
|
|
|
} |
|
|
|
@case ('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' }" |
|
|
|
/> |
|
|
|
</div> |
|
|
|
} |
|
|
|
@case ('select') { |
|
|
|
<ng-template [ngTemplateOutlet]="label" /> |
|
|
|
<select |
|
|
|
#field |
|
|
|
[id]="prop().id" |
|
|
|
[formControlName]="prop().name" |
|
|
|
[abpDisabled]="disabled" |
|
|
|
class="form-select form-control" |
|
|
|
> |
|
|
|
@for (option of options$ | async; track option.value) { |
|
|
|
<option [ngValue]="option.value"> |
|
|
|
@if (prop().isExtra) { |
|
|
|
{{ '::' + option.key | abpLocalization }} |
|
|
|
} @else { |
|
|
|
{{ option.key }} |
|
|
|
} |
|
|
|
</option> |
|
|
|
} |
|
|
|
</select> |
|
|
|
} |
|
|
|
@case ('multiselect') { |
|
|
|
<ng-template [ngTemplateOutlet]="label"></ng-template> |
|
|
|
<abp-extensible-form-multi-select |
|
|
|
[prop]="prop()" |
|
|
|
[options]="options$ | async" |
|
|
|
[formControlName]="prop().name" |
|
|
|
[abpDisabled]="disabled" |
|
|
|
/> |
|
|
|
} |
|
|
|
@case ('typeahead') { |
|
|
|
<ng-template [ngTemplateOutlet]="label" /> |
|
|
|
<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> |
|
|
|
} |
|
|
|
@case ('date') { |
|
|
|
<ng-template [ngTemplateOutlet]="label" /> |
|
|
|
<input |
|
|
|
[id]="prop().id" |
|
|
|
[formControlName]="prop().name" |
|
|
|
(click)="datepicker.open()" |
|
|
|
(keyup.space)="datepicker.open()" |
|
|
|
ngbDatepicker |
|
|
|
#datepicker="ngbDatepicker" |
|
|
|
type="text" |
|
|
|
class="form-control" |
|
|
|
/> |
|
|
|
} |
|
|
|
@case ('time') { |
|
|
|
<ng-template [ngTemplateOutlet]="label" /> |
|
|
|
<ngb-timepicker [formControlName]="prop().name" /> |
|
|
|
} |
|
|
|
@case ('dateTime') { |
|
|
|
<ng-template [ngTemplateOutlet]="label" /> |
|
|
|
<abp-extensible-date-time-picker [prop]="prop()" [meridian]="meridian$ | async" /> |
|
|
|
} |
|
|
|
@case ('textarea') { |
|
|
|
<ng-template [ngTemplateOutlet]="label" /> |
|
|
|
<textarea |
|
|
|
#field |
|
|
|
[id]="prop().id" |
|
|
|
[formControlName]="prop().name" |
|
|
|
[abpDisabled]="disabled" |
|
|
|
[readonly]="readonly" |
|
|
|
class="form-control" |
|
|
|
></textarea> |
|
|
|
} |
|
|
|
@case ('passwordinputgroup') { |
|
|
|
<ng-template [ngTemplateOutlet]="label" /> |
|
|
|
<div class="input-group form-group" validationTarget> |
|
|
|
<input |
|
|
|
class="form-control" |
|
|
|
[id]="prop().id" |
|
|
|
[formControlName]="prop().name" |
|
|
|
[abpShowPassword]="showPassword" |
|
|
|
/> |
|
|
|
<button class="btn btn-secondary" type="button" (click)="showPassword = !showPassword"> |
|
|
|
<i |
|
|
|
class="fa" |
|
|
|
aria-hidden="true" |
|
|
|
[class]="{ 'fa-eye-slash': !showPassword, 'fa-eye': showPassword }" |
|
|
|
></i> |
|
|
|
</button> |
|
|
|
</div> |
|
|
|
} |
|
|
|
</select> |
|
|
|
} |
|
|
|
@case ('multiselect') { |
|
|
|
<ng-template [ngTemplateOutlet]="label"></ng-template> |
|
|
|
<abp-extensible-form-multi-select [prop]="prop()" [options]="options$ | async" [formControlName]="prop().name" |
|
|
|
[abpDisabled]="disabled" /> |
|
|
|
} |
|
|
|
@case ('typeahead') { |
|
|
|
<ng-template [ngTemplateOutlet]="label" /> |
|
|
|
<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> |
|
|
|
} |
|
|
|
@case ('date') { |
|
|
|
<ng-template [ngTemplateOutlet]="label" /> |
|
|
|
<input [id]="prop().id" [formControlName]="prop().name" (click)="datepicker.open()" (keyup.space)="datepicker.open()" |
|
|
|
ngbDatepicker #datepicker="ngbDatepicker" type="text" class="form-control" /> |
|
|
|
} |
|
|
|
@case ('time') { |
|
|
|
<ng-template [ngTemplateOutlet]="label" /> |
|
|
|
<ngb-timepicker [formControlName]="prop().name" /> |
|
|
|
} |
|
|
|
@case ('dateTime') { |
|
|
|
<ng-template [ngTemplateOutlet]="label" /> |
|
|
|
<abp-extensible-date-time-picker [prop]="prop()" [meridian]="meridian$ | async" /> |
|
|
|
} |
|
|
|
@case ('textarea') { |
|
|
|
<ng-template [ngTemplateOutlet]="label" /> |
|
|
|
<textarea #field [id]="prop().id" [formControlName]="prop().name" [abpDisabled]="disabled" [readonly]="readonly" |
|
|
|
class="form-control"></textarea> |
|
|
|
} |
|
|
|
@case ('passwordinputgroup') { |
|
|
|
<ng-template [ngTemplateOutlet]="label" /> |
|
|
|
<div class="input-group form-group" validationTarget> |
|
|
|
<input class="form-control" [id]="prop().id" [formControlName]="prop().name" [abpShowPassword]="showPassword" /> |
|
|
|
<button class="btn btn-secondary" type="button" (click)="showPassword = !showPassword"> |
|
|
|
<i class="fa" aria-hidden="true" [class]="{ |
|
|
|
'fa-eye-slash': !showPassword, |
|
|
|
'fa-eye': showPassword, |
|
|
|
}"></i> |
|
|
|
</button> |
|
|
|
</div> |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@if (prop().formText) { |
|
|
|
<small class="text-muted d-block">{{ prop().formText | abpLocalization }}</small> |
|
|
|
<small class="text-muted d-block">{{ prop().formText | abpLocalization }}</small> |
|
|
|
} |
|
|
|
</div> |
|
|
|
</ng-container> |
|
|
|
@ -95,19 +152,23 @@ |
|
|
|
<label [htmlFor]="prop().id" [class]="classes || 'form-label d-inline-block'"> |
|
|
|
<span class="d-inline-flex align-items-center gap-1 text-nowrap"> |
|
|
|
@if (prop().displayTextResolver) { |
|
|
|
{{ prop().displayTextResolver(data()) | abpLocalization }} |
|
|
|
{{ prop().displayTextResolver(data()) | abpLocalization }} |
|
|
|
} @else { |
|
|
|
@if (prop().isExtra) { |
|
|
|
{{ '::' + prop().displayName | abpLocalization }} |
|
|
|
} @else { |
|
|
|
{{ prop().displayName | abpLocalization }} |
|
|
|
} |
|
|
|
@if (prop().isExtra) { |
|
|
|
{{ '::' + prop().displayName | abpLocalization }} |
|
|
|
} @else { |
|
|
|
{{ prop().displayName | abpLocalization }} |
|
|
|
} |
|
|
|
} |
|
|
|
{{ asterisk }} |
|
|
|
@if (prop().tooltip) { |
|
|
|
<i [ngbTooltip]="prop().tooltip.text | abpLocalization" [placement]="prop().tooltip.placement || 'auto'" |
|
|
|
container="body" class="bi bi-info-circle"></i> |
|
|
|
<i |
|
|
|
[ngbTooltip]="prop().tooltip.text | abpLocalization" |
|
|
|
[placement]="prop().tooltip.placement || 'auto'" |
|
|
|
container="body" |
|
|
|
class="bi bi-info-circle" |
|
|
|
></i> |
|
|
|
} |
|
|
|
</span> |
|
|
|
</label> |
|
|
|
</ng-template> |
|
|
|
</ng-template> |
|
|
|
|