An Angular admin template
Open the command prompt at the root of the project and type the following command.
npm install
Edit environment files /environments/environment.ts
and /environments/environment.prod.ts
in relation to your development and deployment environment.
Run the application and enjoy ☻:
ng serve
Enter username and password to login. You can adjust the authentication system as you wish.
Create your components in module main
ng generate component main/mycomponentname
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.
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>
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
};
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>