zeprototypeng-community/zeprototypeng
An Angular admin template
ZePrototype NG
An Angular admin template
Prerequisites
Installation
Open the command prompt at the root of the project and type the following command.
npm install
Configuration
Edit environment files /environments/environment.ts and /environments/environment.prod.ts in relation to your development and deployment environment.
Quick Start
Run the application and enjoy ☻:
ng serve
Usage
Authentication page
Enter username and password to login. You can adjust the authentication system as you wish.
Components
Create your components in module main
ng generate component main/mycomponentname
Application routes configuration
Add a property to appRoutes const variable in /src/app/application/routing/app-routes.ts file :
export const appRoutes = {
...
myroute: { path: 'my-route-path', label: 'My route label' }
};
Append route configuration to children property of first Route object in /src/app/main/main-routing.module.ts file:
...
{
path: appRoutes.myroute.path, // the property that you added to the constant variable
component: MyComponent, // the generated component
data: { breadcrumb: appRoutes.myroute.label } //Label to display
}
Your component is now accessible through the left sidebar.
Generate a form
Open /src/app/application/forms/forms.ts file, add these lines to formIds and Iform const variables.
...
export const formIds = {
...
myFormId: 7 // Your form id must be unique
}
...
export const forms: Iform[] = [
...
{
id: formIds.myFormId,
controls: [
{
// refer to the 'controls' property of the object whose 'id' property value is equal to 'formIds.testFormId'
}
]
},
]
Now, edit your component like this:
/src/app/main/my-component/my-component.component.ts
import { Component, OnInit } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { formIds } from 'src/app/application/forms/forms';
import { Iform } from 'src/app/core/form-module/dynamic-form/dynamic-form.component';
import { FormService } from 'src/app/core/form-module/services/form.service';
import { UiNotificationService, UIStateStatusCode } from 'src/app/partials/ui-notification/ui-notification.service';
...
export class MyComponent implements OnInit {
form: Iform;
formGroup: FormGroup;
constructor(private uiState: UiNotificationService, private client: HttpRequestService, private formService: FormService) { }
ngOnInit(): void {
this.buildForm();
}
async buildForm() {
this.form = await this.formService.getForm(formIds.myFormId);
this.formGroup = this.formService.getFormGroup(this.form.controls);
}
}
/src/app/main/my-component/my-component.component.html
<form [formGroup]="formGroup" *ngIf="formGroup">
<app-dynamic-form [formGroup]="formGroup" [form]="form"></app-dynamic-form>
</form>
API routes configuration
Add a property to minRoutes and apiRoutes const variables in /src/app/application/routing/app-routes.ts file :
export const minRoutes = {
...
my_min_api_route: 'my-api-route-prefix-name'
};
export const apiRoutes = {
...
my_api_route: environment.APP_SERVER_HOST + environment.URLPART1 + minRoutes.my_min_api_route
};
List, Create, Update and Delete data
Create a .ts file under the directory /src/app/application/models/ as a model.
export class MyModel {
public id: number = undefined;
public label: string = undefined;
}
Import model into component and enjoy the result.
/src/app/main/my-component/my-component.component.ts
import { Component, OnInit } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { ClrDatagridStateInterface } from '@clr/angular';
import { Subject, takeUntil } from 'rxjs';
import { formIds } from 'src/app/application/forms/forms';
import { MyModel } from 'src/app/application/models/MyModel';
import { responsesMessages } from 'src/app/application/response/messages';
import { PaginateResponse, getResponseState, getResponseData, getResponseCode } from 'src/app/application/response/response';
import { apiRoutes } from 'src/app/application/routing/api-routes';
import { Iform } from 'src/app/core/form-module/dynamic-form/dynamic-form.component';
import { FormService } from 'src/app/core/form-module/services/form.service';
import { HttpRequestService } from 'src/app/core/http/http-request.service';
import { UiNotificationService, UIStateStatusCode } from 'src/app/partials/ui-notification/ui-notification.service';
import { getFiltersFromDatagrid } from 'src/app/core/util/datagrid-util';
@Component({
selector: 'app-my-component',
templateUrl: './my-component.component.html',
styleUrls: ['./my-component.component.scss']
})
export class MyComponent implements OnInit {
_destroy$ = new Subject();
form : Iform;
formGroup : FormGroup;
url = apiRoutes.my_api_route;
singleData: MyModel;
data: PaginateResponse = new PaginateResponse(new MyModel);
initialGridState: ClrDatagridStateInterface = { page: { current: 1, size: 10 } };
loading = true;
updating = false;
openModal = false;
constructor(private uiState: UiNotificationService, private client: HttpRequestService, private formService: FormService) { }
ngOnInit(): void {
this.buildForm();
}
async buildForm() {
this.form = await this.formService.getForm(formIds.myFormId);
this.formGroup = this.formService.getFormGroup(this.form.controls);
}
/**
* get data
*
* @param param
*/
getData(param?: string) {
this.loading = true;
this.uiState.startAction();
param = param ? param : getFiltersFromDatagrid(this.initialGridState);
this.client.get(this.url + '?' + param)
.pipe(takeUntil(this._destroy$))
.subscribe((result) => {
if (getResponseState(result)) {
this.data = getResponseData(result);
this.uiState.endAction();
} else {
this.uiState.endAction(getResponseCode(result), responsesMessages.FAILED);
}
this.loading = false;
})
}
/**
* submit form data
*
* @param param
*/
onSubmit(param: FormGroup) {
this.uiState.startAction();
let dataToSend = param.getRawValue();
this.client.post(this.url, dataToSend)
.pipe(takeUntil(this._destroy$))
.subscribe((result) => {
if (getResponseState(result)) {
this.formGroup.reset();
this.getData();
this.uiState.endAction(UIStateStatusCode.CREATED, responsesMessages.SUCCESS);
} else {
this.uiState.endAction(getResponseCode(result), responsesMessages.FAILED);
}
});
}
/**
* set form with values from the ressource id
*
* @param id
*/
onEdit(id: number) {
this.client.get(this.url + '/' + id)
.pipe(takeUntil(this._destroy$))
.subscribe((result) => {
if (getResponseState(result)) {
this.singleData = getResponseData(result);
Object.keys(this.singleData).forEach((v, i) => {
this.formGroup.controls?.[v]?.setValue(this.singleData?.[v]);
this.updating = true;
})
this.uiState.endAction(UIStateStatusCode.CREATED, responsesMessages.SUCCESS);
} else {
this.uiState.endAction(getResponseCode(result), responsesMessages.FAILED);
}
});
}
/**
* cancel form editing
*/
onCancel() {
this.formGroup.reset();
this.updating = false;
}
/**
* update data
*
* @param param
*/
onUpdate(param: FormGroup) {
this.uiState.startAction();
let dataToSend = param.getRawValue();
this.client.put(this.url + '/' + this.singleData.id, dataToSend)
.pipe(takeUntil(this._destroy$))
.subscribe((result) => {
if (getResponseState(result)) {
this.formGroup.reset();
this.updating = false;
this.getData();
this.uiState.endAction(UIStateStatusCode.OK, responsesMessages.SUCCESS);
} else {
this.uiState.endAction(getResponseCode(result), responsesMessages.FAILED);
}
});
}
/**
* attempt to delete data
*/
onDeleteAttempt(id: number) {
if (!this.singleData) {
this.singleData = new MyModel();
}
this.singleData.id = id;
this.openModal = true;
}
/**
* delete data by the given resource id
*
* @param id
*/
onDelete(id: number) {
this.uiState.startAction();
this.client.delete(this.url + '/' + id)
.pipe(takeUntil(this._destroy$))
.subscribe((result) => {
if (getResponseState(result)) {
this.getData();
this.uiState.endAction(UIStateStatusCode.OK, responsesMessages.SUCCESS);
} else {
this.uiState.endAction(getResponseCode(result), responsesMessages.FAILED);
}
this.openModal = false;
});
}
/**
* on datagrid refresh event
*
* @param state
*/
onDgRefresh = (state: ClrDatagridStateInterface) => {
this.getData(getFiltersFromDatagrid(state))
}
ngOnDestroy(): void {
this._destroy$.next('');
}
}
/src/app/main/my-component/my-component.component.html
<form [formGroup]="formGroup" *ngIf="formGroup">
<app-dynamic-form [formGroup]="formGroup" [form]="form"></app-dynamic-form>
<button class="btn btn-sm btn-success" type="submit" *ngIf="updating == false" [disabled]="formGroup.invalid">
SAVE
</button>
<button class="btn btn-sm btn-success" type="button" *ngIf="updating == true" (click)="onUpdate(formGroup)" [disabled]="formGroup.invalid">
EDIT
</button>
<button class="btn btn-sm btn-danger" type="button" *ngIf="updating == true" (click)="onCancel()">
CANCEL
</button>
</form>
<clr-datagrid (clrDgRefresh)="onDgRefresh($event)" [clrDgLoading]="loading">
<clr-dg-column>ID</clr-dg-column>
<clr-dg-column>Label</clr-dg-column>
<clr-dg-row *ngFor="let item of data.data">
<clr-dg-cell>{{item.id}}</clr-dg-cell>
<clr-dg-cell>{{item.label}}</clr-dg-cell>
<clr-dg-action-overflow>
<button class="action-item" (click)="onEdit(item.id)">MODIFIER</button>
<button class="action-item" (click)="onDeleteAttempt(item.id)">SUPPRIMER</button>
</clr-dg-action-overflow>
</clr-dg-row>
<clr-dg-footer>
<clr-dg-pagination #pagination [clrDgPageSize]="initialGridState.page.size" [clrDgTotalItems]="data?.total">
<clr-dg-page-size [clrPageSizeOptions]="[10, 20, 30]"></clr-dg-page-size>
{{ pagination.firstItem + 1 }} - {{ pagination.lastItem + 1 }} of {{ pagination.totalItems }} elements
</clr-dg-pagination>
</clr-dg-footer>
</clr-datagrid>
<clr-modal [(clrModalOpen)]="openModal">
<h3 class="modal-title">DELETE</h3>
<div class="modal-body">
<p>Do you want to delete?</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-sm btn-outline" (click)="openModal = false">CANCEL</button>
<button type="button" class="btn btn-sm btn-danger" (click)="onDelete(singleData.id)">YES, CONFIRM</button>
</div>
</clr-modal>