├── .gitignore
├── LICENSE
├── README.md
├── app
├── _content
│ ├── app.less
│ └── modal.less
├── _directives
│ ├── index.ts
│ └── modal.component.ts
├── _services
│ ├── index.ts
│ └── modal.service.ts
├── app.component.html
├── app.component.ts
├── app.module.ts
├── app.routing.ts
├── home
│ ├── home.component.html
│ ├── home.component.ts
│ └── index.ts
├── main.ts
└── test-page
│ ├── index.ts
│ ├── test-page.component.html
│ └── test-page.component.ts
├── index.html
├── package-lock.json
├── package.json
├── systemjs.config.js
└── tsconfig.json
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 |
6 | # Runtime data
7 | pids
8 | *.pid
9 | *.seed
10 |
11 | # Directory for instrumented libs generated by jscoverage/JSCover
12 | lib-cov
13 |
14 | # Coverage directory used by tools like istanbul
15 | coverage
16 |
17 | # nyc test coverage
18 | .nyc_output
19 |
20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
21 | .grunt
22 |
23 | # node-waf configuration
24 | .lock-wscript
25 |
26 | # Compiled binary addons (http://nodejs.org/api/addons.html)
27 | build/Release
28 |
29 | # Dependency directories
30 | node_modules
31 | jspm_packages
32 | typings
33 |
34 | # Optional npm cache directory
35 | .npm
36 |
37 | # Optional REPL history
38 | .node_repl_history
39 |
40 | # Generated files
41 | app/**/*.js
42 | app/**/*.js.map
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Jason Watmore
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # angular2-custom-modal
2 |
3 | Angular 2 Custom Modal
4 |
5 | To see a demo and further details go to http://jasonwatmore.com/post/2017/01/24/angular-2-custom-modal-window-dialog-box
--------------------------------------------------------------------------------
/app/_content/app.less:
--------------------------------------------------------------------------------
1 | /* EXAMPLE STYLES
2 | -------------------------------*/
3 | body {
4 | font-family: roboto;
5 | padding: 20px;
6 | }
7 |
8 | nav {
9 | margin-bottom: 20px;
10 | padding-bottom: 20px;
11 | border-bottom: 1px solid #ddd;
12 |
13 | a {
14 | margin-right: 8px;
15 | }
16 | }
17 |
18 | h1 {
19 | font-weight: normal;
20 | margin-top: 0;
21 | }
22 |
23 | input[type="text"] {
24 | display:block;
25 | width: 100%;
26 | font-family: roboto;
27 | }
28 |
29 | .credits {
30 | margin-top: 30px;
31 | border-top: 1px solid #ddd;
32 | text-align: center;
33 | }
34 |
35 |
--------------------------------------------------------------------------------
/app/_content/modal.less:
--------------------------------------------------------------------------------
1 | /* MODAL STYLES
2 | -------------------------------*/
3 | modal {
4 | /* modals are hidden by default */
5 | display: none;
6 |
7 | .modal {
8 | /* modal container fixed across whole screen */
9 | position: fixed;
10 | top: 0;
11 | right: 0;
12 | bottom: 0;
13 | left: 0;
14 |
15 | /* z-index must be higher than .modal-background */
16 | z-index: 1000;
17 |
18 | /* enables scrolling for tall modals */
19 | overflow: auto;
20 |
21 | .modal-body {
22 | padding: 20px;
23 | background: #fff;
24 |
25 | /* margin exposes part of the modal background */
26 | margin: 40px;
27 | }
28 | }
29 |
30 | .modal-background {
31 | /* modal background fixed across whole screen */
32 | position: fixed;
33 | top: 0;
34 | right: 0;
35 | bottom: 0;
36 | left: 0;
37 |
38 | /* semi-transparent black */
39 | background-color: #000;
40 | opacity: 0.75;
41 |
42 | /* z-index must be below .modal and above everything else */
43 | z-index: 900;
44 | }
45 | }
46 |
47 | body.modal-open {
48 | /* body overflow is hidden to hide main scrollbar when modal window is open */
49 | overflow: hidden;
50 | }
51 |
--------------------------------------------------------------------------------
/app/_directives/index.ts:
--------------------------------------------------------------------------------
1 | export * from './modal.component';
--------------------------------------------------------------------------------
/app/_directives/modal.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, ElementRef, Input, OnInit, OnDestroy } from '@angular/core';
2 | import * as $ from 'jquery';
3 |
4 | import { ModalService } from '../_services/index';
5 |
6 | @Component({
7 | moduleId: module.id.toString(),
8 | selector: 'modal',
9 | template: '
) so it can be displayed above everything else 30 | this.element.appendTo('body'); 31 | 32 | // close modal on background click 33 | this.element.on('click', function (e: any) { 34 | var target = $(e.target); 35 | if (!target.closest('.modal-body').length) { 36 | modal.close(); 37 | } 38 | }); 39 | 40 | // add self (this modal instance) to the modal service so it's accessible from controllers 41 | this.modalService.add(this); 42 | } 43 | 44 | // remove self from modal service when directive is destroyed 45 | ngOnDestroy(): void { 46 | this.modalService.remove(this.id); 47 | this.element.remove(); 48 | } 49 | 50 | // open modal 51 | open(): void { 52 | this.element.show(); 53 | $('body').addClass('modal-open'); 54 | } 55 | 56 | // close modal 57 | close(): void { 58 | this.element.hide(); 59 | $('body').removeClass('modal-open'); 60 | } 61 | } -------------------------------------------------------------------------------- /app/_services/index.ts: -------------------------------------------------------------------------------- 1 | export * from './modal.service'; 2 | -------------------------------------------------------------------------------- /app/_services/modal.service.ts: -------------------------------------------------------------------------------- 1 | import * as _ from 'underscore'; 2 | 3 | export class ModalService { 4 | private modals: any[] = []; 5 | 6 | add(modal: any) { 7 | // add modal to array of active modals 8 | this.modals.push(modal); 9 | } 10 | 11 | remove(id: string) { 12 | // remove modal from array of active modals 13 | let modalToRemove = _.findWhere(this.modals, { id: id }); 14 | this.modals = _.without(this.modals, modalToRemove); 15 | } 16 | 17 | open(id: string) { 18 | // open modal specified by id 19 | let modal = _.findWhere(this.modals, { id: id }); 20 | modal.open(); 21 | } 22 | 23 | close(id: string) { 24 | // close modal specified by id 25 | let modal = _.find(this.modals, { id: id }); 26 | modal.close(); 27 | } 28 | } -------------------------------------------------------------------------------- /app/app.component.html: -------------------------------------------------------------------------------- 1 | 2 |
9 | 10 | 11 |
13 | Angular 2 - Custom Modal Window / Dialog Box 14 |
15 |16 | JasonWatmore.com 17 |
18 |19 | -------------------------------------------------------------------------------- /app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | moduleId: module.id.toString(), 5 | selector: 'app', 6 | templateUrl: 'app.component.html' 7 | }) 8 | 9 | export class AppComponent { } -------------------------------------------------------------------------------- /app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { BrowserModule } from '@angular/platform-browser'; 3 | import { FormsModule } from '@angular/forms'; 4 | 5 | import { AppComponent } from './app.component'; 6 | import { routing } from './app.routing'; 7 | 8 | import { ModalComponent } from './_directives/index'; 9 | import { ModalService } from './_services/index'; 10 | import { HomeComponent } from './home/index'; 11 | import { TestPageComponent } from './test-page/index'; 12 | 13 | @NgModule({ 14 | imports: [ 15 | BrowserModule, 16 | FormsModule, 17 | routing 18 | ], 19 | declarations: [ 20 | AppComponent, 21 | ModalComponent, 22 | HomeComponent, 23 | TestPageComponent 24 | ], 25 | providers: [ 26 | ModalService 27 | ], 28 | bootstrap: [AppComponent] 29 | }) 30 | 31 | export class AppModule { } -------------------------------------------------------------------------------- /app/app.routing.ts: -------------------------------------------------------------------------------- 1 | import { Routes, RouterModule } from '@angular/router'; 2 | 3 | import { HomeComponent } from './home/index'; 4 | import { TestPageComponent } from './test-page/index'; 5 | 6 | const appRoutes: Routes = [ 7 | { path: '', component: HomeComponent }, 8 | { path: 'test-page', component: TestPageComponent }, 9 | 10 | // otherwise redirect to home 11 | { path: '**', redirectTo: '' } 12 | ]; 13 | 14 | export const routing = RouterModule.forRoot(appRoutes); -------------------------------------------------------------------------------- /app/home/home.component.html: -------------------------------------------------------------------------------- 1 |
{{bodyText}}
4 | 5 | 6 |
7 |
8 |
13 | Home page text:
14 | A Custom Modal!
12 | A Tall Custom Modal!
25 |
26 |
This one doesn't have any modals...
4 |-------------------------------------------------------------------------------- /app/test-page/test-page.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | moduleId: module.id.toString(), 5 | templateUrl: 'test-page.component.html' 6 | }) 7 | 8 | export class TestPageComponent { 9 | } -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 24 | 25 |
28 |