Browse Source

Merge pull request #15741 from abpframework/feat-input-wrapper

Feat input wrapper
pull/15800/head
Mahmut Gundogdu 4 years ago
committed by GitHub
parent
commit
127b0f265d
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 58
      npm/ng-packs/angular.json
  2. 6
      npm/ng-packs/apps/dev-app/src/app/app.module.ts
  3. 20
      npm/ng-packs/packages/identity/src/lib/components/users/users.component.html
  4. 38
      npm/ng-packs/packages/identity/src/lib/components/users/users.component.ts
  5. 45
      npm/ng-packs/packages/theme-shared/src/lib/components/checkbox/checkbox.component.ts
  6. 46
      npm/ng-packs/packages/theme-shared/src/lib/components/form-input/form-input.component.ts
  7. 4
      npm/ng-packs/packages/theme-shared/src/lib/enums/form.ts
  8. 1
      npm/ng-packs/packages/theme-shared/src/lib/enums/index.ts
  9. 44
      npm/ng-packs/packages/theme-shared/src/lib/tests/checkbox.component.spec.ts
  10. 46
      npm/ng-packs/packages/theme-shared/src/lib/tests/form-input.component.spec.ts
  11. 8
      npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts
  12. 4
      npm/ng-packs/tsconfig.base.json

58
npm/ng-packs/angular.json

@ -200,50 +200,50 @@
"bundleName": "bootstrap-dim"
},
{
"input": "node_modules/@volo/ngx-lepton-x.lite/assets/css/ng-bundle.css",
"inject": false,
"bundleName": "ng-bundle"
"input": "node_modules/@volo/ngx-lepton-x.lite/assets/css/ng-bundle.css",
"inject": false,
"bundleName": "ng-bundle"
},
{
"input": "node_modules/@volo/ngx-lepton-x.lite/assets/css/side-menu/layout-bundle.css",
"inject": false,
"bundleName": "layout-bundle"
"input": "node_modules/@volo/ngx-lepton-x.lite/assets/css/side-menu/layout-bundle.css",
"inject": false,
"bundleName": "layout-bundle"
},
{
"input": "node_modules/@abp/ng.theme.lepton-x/assets/css/abp-bundle.css",
"inject": false,
"bundleName": "abp-bundle"
"input": "node_modules/@abp/ng.theme.lepton-x/assets/css/abp-bundle.css",
"inject": false,
"bundleName": "abp-bundle"
},
{
"input": "node_modules/@volo/ngx-lepton-x.lite/assets/css/bootstrap-dim.rtl.css",
"inject": false,
"bundleName": "bootstrap-dim.rtl"
"input": "node_modules/@volo/ngx-lepton-x.lite/assets/css/bootstrap-dim.rtl.css",
"inject": false,
"bundleName": "bootstrap-dim.rtl"
},
{
"input": "node_modules/@volo/ngx-lepton-x.lite/assets/css/ng-bundle.rtl.css",
"inject": false,
"bundleName": "ng-bundle.rtl"
"input": "node_modules/@volo/ngx-lepton-x.lite/assets/css/ng-bundle.rtl.css",
"inject": false,
"bundleName": "ng-bundle.rtl"
},
{
"input": "node_modules/@volo/ngx-lepton-x.lite/assets/css/side-menu/layout-bundle.rtl.css",
"inject": false,
"bundleName": "layout-bundle.rtl"
"input": "node_modules/@volo/ngx-lepton-x.lite/assets/css/side-menu/layout-bundle.rtl.css",
"inject": false,
"bundleName": "layout-bundle.rtl"
},
{
"input": "node_modules/@abp/ng.theme.lepton-x/assets/css/abp-bundle.rtl.css",
"inject": false,
"bundleName": "abp-bundle.rtl"
"input": "node_modules/@abp/ng.theme.lepton-x/assets/css/abp-bundle.rtl.css",
"inject": false,
"bundleName": "abp-bundle.rtl"
},
{
"input":"node_modules/@volo/ngx-lepton-x.lite/assets/css/font-bundle.rtl.css",
"inject":false,
"bundleName":"font-bundle.rtl"
"input": "node_modules/@volo/ngx-lepton-x.lite/assets/css/font-bundle.rtl.css",
"inject": false,
"bundleName": "font-bundle.rtl"
},
{
"input":"node_modules/@volo/ngx-lepton-x.lite/assets/css/font-bundle.css",
"inject":false,
"bundleName":"font-bundle"
},
"input": "node_modules/@volo/ngx-lepton-x.lite/assets/css/font-bundle.css",
"inject": false,
"bundleName": "font-bundle"
},
{
"input": "node_modules/@fortawesome/fontawesome-free/css/all.min.css",
"inject": true,
@ -756,7 +756,7 @@
}
},
"tags": [],
"implicitDependencies": ["core","oauth"]
"implicitDependencies": ["core", "oauth"]
}
}
}

6
npm/ng-packs/apps/dev-app/src/app/app.module.ts

@ -4,8 +4,8 @@ import { registerLocale } from '@abp/ng.core/locale';
import { IdentityConfigModule } from '@abp/ng.identity/config';
import { SettingManagementConfigModule } from '@abp/ng.setting-management/config';
import { TenantManagementConfigModule } from '@abp/ng.tenant-management/config';
import { ThemeLeptonXModule } from "@abp/ng.theme.lepton-x";
import { SideMenuLayoutModule } from "@abp/ng.theme.lepton-x/layouts";
import { ThemeLeptonXModule } from '@abp/ng.theme.lepton-x';
import { SideMenuLayoutModule } from '@abp/ng.theme.lepton-x/layouts';
import { ThemeSharedModule } from '@abp/ng.theme.shared';
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
@ -36,7 +36,7 @@ import { AbpOAuthModule } from '@abp/ng.oauth';
FeatureManagementModule.forRoot(),
SettingManagementConfigModule.forRoot(),
ThemeLeptonXModule.forRoot(),
SideMenuLayoutModule.forRoot()
SideMenuLayoutModule.forRoot(),
],
providers: [APP_ROUTE_PROVIDER],
declarations: [AppComponent],

20
npm/ng-packs/packages/identity/src/lib/components/users/users.component.html

@ -49,18 +49,24 @@
*ngFor="let roleGroup of roleGroups; let i = index; trackBy: trackByFn"
class="form-check mb-2"
>
<input
type="checkbox"
class="form-check-input"
[attr.id]="'roles-' + i"
<abp-checkbox
*abpReplaceableTemplate="{
inputs:{
checkboxId:'roles-' + i,
label:roles[i].name,
formControl:roleGroup.controls[roles[i].name]
},
componentKey: inputKey
}"
[checkboxId]="'roles-' + i"
[formControl]="roleGroup.controls[roles[i].name]"
/>
<label class="form-check-label" [attr.for]="'roles-' + i">{{ roles[i].name }}</label>
[label]="roles[i].name"
>
</abp-checkbox>
</div>
</ng-template>
</li>
</ul>
<div class="mt-2 fade-in-top" [ngbNavOutlet]="nav"></div>
</form>
</ng-template>

38
npm/ng-packs/packages/identity/src/lib/components/users/users.component.ts

@ -1,12 +1,28 @@
import { ListService, PagedResultDto } from "@abp/ng.core";
import { GetIdentityUsersInput, IdentityRoleDto, IdentityUserDto, IdentityUserService } from "@abp/ng.identity/proxy";
import { ePermissionManagementComponents } from "@abp/ng.permission-management";
import { Confirmation, ConfirmationService, ToasterService } from "@abp/ng.theme.shared";
import { EXTENSIONS_IDENTIFIER, FormPropData, generateFormFromProps } from "@abp/ng.theme.shared/extensions";
import { Component, Injector, OnInit, TemplateRef, TrackByFunction, ViewChild } from "@angular/core";
import { AbstractControl, UntypedFormArray, UntypedFormBuilder, UntypedFormGroup } from "@angular/forms";
import { finalize, switchMap, tap } from "rxjs/operators";
import { eIdentityComponents } from "../../enums/components";
import { ListService, PagedResultDto } from '@abp/ng.core';
import {
GetIdentityUsersInput,
IdentityRoleDto,
IdentityUserDto,
IdentityUserService,
} from '@abp/ng.identity/proxy';
import { ePermissionManagementComponents } from '@abp/ng.permission-management';
import {Confirmation, ConfirmationService, eFormComponets, ToasterService} from '@abp/ng.theme.shared';
import {
EXTENSIONS_IDENTIFIER,
FormPropData,
generateFormFromProps,
} from '@abp/ng.theme.shared/extensions';
import {
Component,
Injector,
OnInit,
TemplateRef,
TrackByFunction,
ViewChild,
} from '@angular/core';
import { AbstractControl, UntypedFormArray, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { finalize, switchMap, tap } from 'rxjs/operators';
import { eIdentityComponents } from '../../enums/components';
@Component({
selector: 'abp-users',
@ -43,7 +59,9 @@ export class UsersComponent implements OnInit {
permissionManagementKey = ePermissionManagementComponents.PermissionManagement;
entityDisplayName?: string;
entityDisplayName: string;
inputKey=eFormComponets.FormCheckboxComponent
trackByFn: TrackByFunction<AbstractControl> = (index, item) => Object.keys(item)[0] || index;

45
npm/ng-packs/packages/theme-shared/src/lib/components/checkbox/checkbox.component.ts

@ -0,0 +1,45 @@
import { AbstractNgModelComponent } from '@abp/ng.core';
import { Component, EventEmitter, forwardRef, Injector, Input, Output } from '@angular/core';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
@Component({
selector: 'abp-checkbox',
template: `
<div class="mb-3">
<input
type="checkbox"
[(ngModel)]="value"
[id]="checkboxId"
[readonly]="checkboxReadonly"
[ngClass]="checkboxClass"
[ngStyle]="checkboxStyle"
(blur)="onBlur.next()"
(focus)="onFocus.next()"
>
<label *ngIf="label" [ngClass]="labelClass" [for]="checkboxId" > {{label | abpLocalization}} </label>
</div>
`,
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => FormCheckboxComponent),
multi: true,
},
]
})
export class FormCheckboxComponent extends AbstractNgModelComponent {
@Input() label?: string;
@Input() labelClass = 'form-check-label';
@Input() checkboxId!: string;
@Input() checkboxStyle = '';
@Input() checkboxClass = 'form-check-input';
@Input() checkboxReadonly = false;
@Output() onBlur = new EventEmitter<void>();
@Output() onFocus = new EventEmitter<void>();
constructor(injector: Injector) {
super(injector);
}
}

46
npm/ng-packs/packages/theme-shared/src/lib/components/form-input/form-input.component.ts

@ -0,0 +1,46 @@
import { AbstractNgModelComponent } from '@abp/ng.core';
import { Component, EventEmitter, forwardRef, Injector, Input, Output } from '@angular/core';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
@Component({
selector: 'abp-form-input',
template: `
<div class="mb-3">
<label class= *ngIf="label" [ngClass]="labelClass" [for]="inputId" > {{label | abpLocalization}} </label>
<input
type="text"
[id]="inputId"
[placeholder]="inputPlaceholder"
[readonly]="inputReadonly"
[ngClass]="inputClass"
[ngStyle]="inputStyle"
(blur)="onBlur.next()"
(focus)="onFocus.next()"
[(ngModel)]="value">
</div>
`,
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => FormInputComponent),
multi: true,
},
]
})
export class FormInputComponent extends AbstractNgModelComponent {
@Input() inputId!: string;
@Input() inputReadonly: boolean = false;
@Input() label: string = '';
@Input() labelClass = 'form-label';
@Input() inputPlaceholder: string = '';
@Input() inputType: string = 'text';
@Input() inputStyle: string = '';
@Input() inputClass: string = 'form-control';
@Output() onBlur = new EventEmitter<void>();
@Output() onFocus = new EventEmitter<void>();
constructor(injector: Injector) {
super(injector);
}
}

4
npm/ng-packs/packages/theme-shared/src/lib/enums/form.ts

@ -0,0 +1,4 @@
export enum eFormComponets {
FormInputComponent = 'FormInputComponent',
FormCheckboxComponent = 'FormCheckboxComponent',
}

1
npm/ng-packs/packages/theme-shared/src/lib/enums/index.ts

@ -1 +1,2 @@
export * from './form';
export * from './route-names';

44
npm/ng-packs/packages/theme-shared/src/lib/tests/checkbox.component.spec.ts

@ -0,0 +1,44 @@
import { createHostFactory, SpectatorHost } from '@ngneat/spectator/jest';
import { FormCheckboxComponent } from '../components/checkbox/checkbox.component';
describe('FormCheckboxComponent', () => {
let spectator: SpectatorHost<FormCheckboxComponent>;
const createHost = createHostFactory(FormCheckboxComponent);
beforeEach(
() =>
(spectator = createHost(
'<abp-checkbox></abp-checkbox>',
{
hostProps: { attributes: { autofocus: '', name: 'abp-checkbox' } },
},
)),
);
it('should display the input', () => {
expect(spectator.query('input')).toBeTruthy();
});
it('should equal the default classes to form-check-input', () => {
expect(spectator.query('input')).toHaveClass('form-check-input');
});
it('should equal the default type to checkbox', () => {
expect(spectator.query('input')).toHaveAttribute('type', 'checkbox');
});
it('should be readonly when checkboxReadonly is true', () => {
spectator.component.checkboxReadonly = true;
spectator.detectComponentChanges();
expect(spectator.query('[readonly]')).toBeTruthy();
});
it('should not contain readonly when checboxReadonly is false', () => {
spectator.component.checkboxReadonly = false;
spectator.detectComponentChanges();
expect(spectator.query('[disabled]')).toBeFalsy();
});
});

46
npm/ng-packs/packages/theme-shared/src/lib/tests/form-input.component.spec.ts

@ -0,0 +1,46 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { createHostFactory, SpectatorHost } from '@ngneat/spectator/jest';
import { FormInputComponent } from '../components/form-input/form-input.component';
describe('FormInputComponent', () => {
let spectator: SpectatorHost<FormInputComponent>;
const createHost = createHostFactory(FormInputComponent);
beforeEach(
() =>
(spectator = createHost(
'<abp-form-input></abp-form-input>',
{
hostProps: { attributes: { autofocus: '', name: 'abp-form-input' } },
},
)),
);
it('should display the input', () => {
expect(spectator.query('input')).toBeTruthy();
});
it('should equal the default classes to form-control', () => {
expect(spectator.query('input')).toHaveClass('form-control');
});
it('should equal the default type to text', () => {
expect(spectator.query('input')).toHaveAttribute('type', 'text');
});
it('should be readonly when inputReadonly is true', () => {
spectator.component.inputReadonly = true;
spectator.detectComponentChanges();
expect(spectator.query('[readonly]')).toBeTruthy();
});
it('should not contain readonly when inputReadonly is false', () => {
spectator.component.inputReadonly = false;
spectator.detectComponentChanges();
expect(spectator.query('[disabled]')).toBeFalsy();
});
});

8
npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts

@ -38,7 +38,8 @@ import { CONFIRMATION_ICONS, DEFAULT_CONFIRMATION_ICONS } from './tokens/confirm
import { PasswordComponent } from './components/password/password.component';
import { CardModule } from './components/card/card.module';
import { AbpVisibleDirective } from './directives';
import { FormInputComponent } from './components/form-input/form-input.component';
import { FormCheckboxComponent } from './components/checkbox/checkbox.component';
const declarationsWithExports = [
BreadcrumbComponent,
@ -56,6 +57,8 @@ const declarationsWithExports = [
LoadingDirective,
ModalCloseDirective,
AbpVisibleDirective,
FormInputComponent,
FormCheckboxComponent
];
@NgModule({
@ -66,6 +69,7 @@ const declarationsWithExports = [
NgbPaginationModule,
EllipsisModule,
CardModule,
],
declarations: [...declarationsWithExports, HttpErrorWrapperComponent],
exports: [
@ -77,7 +81,7 @@ const declarationsWithExports = [
],
providers: [DatePipe],
})
export class BaseThemeSharedModule {}
export class BaseThemeSharedModule { }
@NgModule({
imports: [BaseThemeSharedModule],

4
npm/ng-packs/tsconfig.base.json

@ -30,6 +30,7 @@
"@abp/ng.identity": ["packages/identity/src/public-api.ts"],
"@abp/ng.identity/config": ["packages/identity/config/src/public-api.ts"],
"@abp/ng.identity/proxy": ["packages/identity/proxy/src/public-api.ts"],
"@abp/ng.oauth": ["packages/oauth/src/public-api.ts"],
"@abp/ng.permission-management": ["packages/permission-management/src/public-api.ts"],
"@abp/ng.permission-management/proxy": [
"packages/permission-management/proxy/src/public-api.ts"
@ -43,8 +44,7 @@
"@abp/ng.theme.basic/testing": ["packages/theme-basic/testing/src/public-api.ts"],
"@abp/ng.theme.shared": ["packages/theme-shared/src/public-api.ts"],
"@abp/ng.theme.shared/extensions": ["packages/theme-shared/extensions/src/public-api.ts"],
"@abp/ng.theme.shared/testing": ["packages/theme-shared/testing/src/public-api.ts"],
"@abp/ng.oauth": ["packages/oauth/src/public-api.ts"]
"@abp/ng.theme.shared/testing": ["packages/theme-shared/testing/src/public-api.ts"]
}
},
"exclude": ["node_modules", "tmp"]

Loading…
Cancel
Save