Angular - Controls - Bootstrap Modal

Bootstrap Modal Popup Forms

Here are portions of the List.component.ds form

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import { Component, OnInit } from '@angular/core';
import { CompanyService } from '../company.service';
import { ActivatedRoute } from '@angular/router';
import { Company } from '../company.model';
import { Router } from '@angular/router';
import { CompanyDetailsComponent } from '../company-details/company-details.component';
import Swal from 'sweetalert2/dist/sweetalert2.js';
import { CommonService } from '../../shared/common.service';

‘ bsModalRef is a pointer to a modal form

import { BsModalRef, BsModalService, ModalOptions} from 'ngx-bootstrap/modal';

@Component({
selector: 'company-list',
templateUrl: './company-list.component.html',
styleUrls: ['./company-list.component.css']
})
export class CompanyListComponent implements OnInit {

‘ we pass in a modal ref????

bsModalRef: BsModalRef;
public companies: Company[]=[];

constructor(
private companyService: CompanyService,
private commonService: CommonService,

‘ constructor needs a bsModalService

private modalService: BsModalService,
) {
}

ngOnInit() {
this.getAllCompanies();
}

public getAllCompanies() {
this.companyService.getAllCompanies()
.subscribe(
result => {
if (result.wasSuccessful === false) {
alert("Error trying to retrieve Companies");
} else {
this.companies = result.model;
}
},
error => {
alert("Error trying to retrieve Companies!");
}
);
}

public onRowClicked(company) {
console.log("row clicked: ", company);

const config = {
class: 'modal-lg',
backdrop: true,
ignoreBackdropClick: true,
initialState: {

‘ the initial state is a place where you define what data is going
‘ to the modal popup (component)

company:company

‘ actually this is PropertyName:Value and it can be comma seperated
}
};


‘ setup modal reference with the component you want displayed, and a
‘ configuration

this.bsModalRef = this.modalService.show(CompanyDetailsComponent, config);

‘ setup what happens when the popup is closed

this.bsModalRef.content.onClose.subscribe(result => {
if(result === true) {
this.getAllCompanies();
}
})

}

public addRecord() {
console.log("Add Record");

const config = {
class: 'modal-lg',
backdrop: true,
ignoreBackdropClick: true,
initialState: {

‘ add record is passing the same information – but null

company:null
}
};

this.bsModalRef = this.modalService.show(CompanyDetailsComponent, config);
this.bsModalRef.content.onClose.subscribe(result => {
if(result === true) {
this.getAllCompanies();
}
})
}

}

Here is the list.html form (There is no modal / popup related logic)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
<div class="mt-1 container-fluid">  
<div class="card">
<div class="card-header">
<div class="row">
<div class="col-10">
<h4>List of Companies</h4>
</div>
<div class="col-2">
<span class="text-right" >
<button
(click)="addRecord()"
class='btn btn-primary'
title='add new Company'
>
<span class='fa fa-plus' aria-hidden='true'></span>
Add Company
</button>
</span>
</div>
</div>
</div>

<div class='card-body'>
<table class='table table-striped table-sm'>
<thead>
<tr>
<th scope='col'></th>
<th scope='col'> ID </th>
<th scope='col'> Code </th>
<th scope='col'> Title </th>
<th scope='col'> Is Active </th>
</tr>
</thead>
<tbody>
<tr *ngFor="let company of companies | paginate: {
itemsPerPage: 10,
currentPage: 1,
totalItems: companies.length
};">
<td>
<button class="btn btn-secondary"
(click)="onRowClicked(company)" >
<i class="fa fa-pencil"></i> Edit</button>
</td>

<td>{{company.id}}</td>
<td>{{company.code}}</td>
<td>{{company.title}}</td>
<td>{{company.isActive}}</td>
<td>
<button class="btn"
(click)="deleteCompany(company)"
class="btn btn-default ml-2" >
<i class="fa fa-trash"></i> Delete</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>

Here is modal.component.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
import { CompanyService } from '../company.service';
import { Company } from '../company.model';
import { FormBuilder, FormControl, Validators } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { CommonService } from '../../shared/common.service';
import { FormGroup } from '@angular/forms';
import Swal from 'sweetalert2';
import { Inject, ViewChild } from '@angular/core';
import { Component, OnInit, Input, ElementRef} from '@angular/core';

‘ boot strap objects

import { BsModalService, BsModalRef } from 'ngx-bootstrap/modal';
import { Result } from '../../shared/models';
import { Subject } from 'rxjs';
import { ToastrService } from 'ngx-toastr';

@Component({
selector: 'company-details',
templateUrl: './company-details.component.html',
styleUrls: ['./company-details.component.css']
})
export class CompanyDetailsComponent implements OnInit {

‘ a little bit of magic – company is one of those parameters
‘ being passed in.

@Input() company:Company;
@ViewChild("txtCode") txtCode: ElementRef;;
public title: string;
errorFormData: any; // API will throw errors into this structure

‘ onClose is a trigger whwich will be trigged during the modal
‘ close process

public onClose: Subject<boolean>;

companyForm = this.formBuilder.group ( {
id: ['', [
Validators.required,
]],
code: ['', [
Validators.required,
Validators.maxLength(24),
]],
title: ['', [
Validators.required,
Validators.maxLength(250),
]],
isActive: ['', [
]],
})

constructor(
private service: CompanyService,
private formBuilder: FormBuilder,
private commonService: CommonService,
private toastr: ToastrService,

as the form is being initialized, it is receiving a copy of the modal
‘ information that is passed in.

public bsModalRef: BsModalRef,
) {
}

ngOnInit() {
this.onClose=new Subject();
if (this.isAddForm()) {
this.title="Add a new Company";
} else {
this.title="Modify an existing Company";
this.loadForm();
}
}

ngAfterViewInit() {
this.txtCode.nativeElement.focus();
}

public isAddForm() {
var flag=this.company?.id;
console.log ("isAddForm - " + flag);
return flag === undefined;
}

loadForm() {
if(this.isAddForm()){
// add mode - form is already initialized, lets blank it out
this.companyForm.setValue ( {
id: null,
code: null,
title: null,
isActive: null,
});
this.title = "Company Add";
} else {
// Edit mode - lets populate the form
let aCompany = this.company;

this.companyForm.setValue ( {
id: aCompany.id,
code: aCompany.code,
title: aCompany.title,
isActive: aCompany.isActive,
});

this.title = "Company Edit";
}



}

public saveCompany() {
this.errorFormData = null;
console.log("saveCompany - ", this.isAddForm());
if (this.isAddForm()) {

}
let company: Company = {
id: this.isAddForm() ? null : this.companyForm.controls.id.value,
code: this.companyForm.controls.code.value,
title: this.companyForm.controls.title.value,
isActive: (this.companyForm.controls.isActive.value == 1 ? true : false),
}

if (this.isAddForm()) {
// add
this.errorFormData = null;
console.log("Add");
this.service.createNewCompany (company )
.subscribe(result => { console.log("Add - Succeeded");
if (result.wasSuccessful === true) {
this.commonService.DisplayToastrMessage("The Company has been added into the system.");
this.closePopupForm('added');
} else {
this.commonService.DisplayErrorWithOk("Error adding Company", result.message.friendlyMessage);
}
},
apiError => {
console.log(`Add - Error. - ` + apiError.error.errors);
if (apiError.error && apiError.error.errors) {
console.log(`Add - Errors - ${apiError.error.errors}`);
this.errorFormData=apiError.error.errors;
};
});
} else {
// edit
console.log("Edit");
this.service.updateCompany(company)
.subscribe(result => {
if (result.wasSuccessful === true) {
this.commonService.DisplayToastrMessage("Company has been Updated");
//this.employeeForm.markAsPristine();
this.closePopupForm('saved');
} else {
this.commonService.DisplayErrorWithOk("Error updating Company", result.message.friendlyMessage);
};
},
apiError => {
if (apiError.error && apiError.error.errors) {
this.errorFormData=apiError.error.error;
};
}
);
}
}

displayMessage(result: any)
{
if (result.wasSuccessful === true) {
this.onClose.next(true);
this.bsModalRef.hide();
this.commonService.DisplayToastrMessage(result.message.friendlyMessage);
} else {
this.commonService.DisplayErrorWithOk('',result.message.friendlyMessage);
};
}


‘ here are where we shut things down.
‘ onclose.next is called to indicate to the main form that the modal is being closed.
‘ bsModalRef.hide is hiding the modal form

closePopupForm(status: string): void {
this.onClose.next(true);
this.bsModalRef.hide();
}
}