Skip to content

component(ModalContainer): modal container initialization#8

Merged
Stradivario merged 15 commits intomasterfrom
7-modal-container-initialization
Oct 17, 2019
Merged

component(ModalContainer): modal container initialization#8
Stradivario merged 15 commits intomasterfrom
7-modal-container-initialization

Conversation

@Stradivario
Copy link
Copy Markdown
Member

@Stradivario Stradivario commented Oct 15, 2019

Issue

Description

Introduces ModalService with capabilities user to choose what kind of template or component he wants to render. The main idea is to have modal-container appended inside body and then providing content inside of this container.

Checklist:

  • Create modal container component like a container wrapper
  • Append this container wrapper inside body
  • Create service to handle creation and deletion of the modal
  • Create ability to inject Data inside modal container when using component as a modal gateway

Screenshot from 2019-10-18 13-26-10
Screenshot from 2019-10-18 13-25-47

Modal Service

Usage

Inject ModalModule from @rxdi/ui-kit/modal

import { ModalModule } from '@rxdi/ui-kit/modal';

@Module({
  imports: [ModalModule.forRoot()]
})
export class AppModule {}

In order to have backdropClose which by default is disabled you need to provide optional config

style With this property you can specify default modal-container CSS

backdropClose when click outside of the visible modal area dialog will close

import { ModalModule } from '@rxdi/ui-kit/modal';

@Module({
  imports: [
    ModalModule.forRoot({
      backdropClose: true,
      style: css`
        .wrapper {
          position: absolute;
          top: 0;
          left: 0;
          align-items: center;
          justify-content: center;
          pointer-events: none;
          width: 100%;
          height: 100%;
        }

        .backdrop {
          width: 100%;
          height: 100%;
          top: 0;
          left: 0;
          position: absolute;
          background-color: rgba(0, 0, 0, 0.5);
          pointer-events: all;
          z-index: 10;
        }

        .content {
          z-index: 20;
          position: absolute;
          pointer-events: all;
        }
      `
    })
  ]
})
export class AppModule {}

Three steps demo modal:

  1. Inject ModalService inside component
import { ModalService } from '@rxdi/ui-kit/modal';

@Component({
  selector: 'modal-view-component',
  template(this: ModalViewComponent) {
    return html`My test modal`;
  }
})
export class ModalViewComponent extends LitElement {
  @Inject(ModalService) private modalService: ModalService;
}
  1. Define descriptor to open modal dialog
openModal() {
  this.modalService.open(html`My Modal Content, <div @click=${this.modalService.close()}>Close</div>`)
}
  1. Now lets execute openModal
import { ModalService } from '@rxdi/ui-kit/modal';
import { html, LitElement, Component } from '@rxdi/lit-html';
import { Inject } from '@rxdi/core';

@Component({
  selector: 'modal-view-component',
  template(this: ModalViewComponent) {
    return html`
      <div @click=${() => this.openModal()}>Open Modal Dialog</div>
    `;
  }
})
export class ModalViewComponent extends LitElement {
  @Inject(ModalService) private modalService: ModalService;

  openModal() {
    this.modalService.open(
      html`
        My Modal Content,
        <div @click=${this.modalService.close()}>Close</div>
      `
    ).subscribe();
  }
}
Basic Usage
import { Component, LitElement, html, css } from '@rxdi/lit-html';
import { Inject } from '@rxdi/core';
import { ModalService } from '@rxdi/ui-kit/modal';

@Component({
  selector: 'modal-view-component',
  template(this: ModalViewComponent) {
    return html`
      <div
        @click=${() => this.openBasicModal()}
        style="cursor:pointer; padding: 20px; background-color: blue"
      >
        Open Basic Modal
      </div>
    `;
  }
})
export class ModalViewComponent extends LitElement {
  @Inject(ModalService)
  private modalService: ModalService;

  openBasicModal() {
    this.modalService.open(
      html`
        <style>
          :host {
            width: 100%;
            height: 100%;
            top: 0;
            left: 0;
            position: absolute;
            background-color: black;
          }
        </style>
        <div
          @click=${() => this.closeModal()}
          style="cursor:pointer; padding: 20px; background-color: blue"
        >
          Close Modal
        </div>
      `
    );
  }

  closeModal() {
    this.modalService.close();
  }
}
Using with Component
import { Component, LitElement, html, css } from '@rxdi/lit-html';
import { Inject, Injector } from '@rxdi/core';
import { ModalService } from '@rxdi/ui-kit/modal/modal.service';
import { MODAL_DIALOG_DATA } from '@rxdi/ui-kit/modal/interface';

/* TestModal Component */
@Component({
  selector: 'test-modal',
  style: css`
    :host {
      width: 100%;
      height: 100%;
      top: 0;
      left: 0;
      position: absolute;
      background-color: black;
    }
  `,
  template(this: TestModal) {
    return html`
      Test Modal ${JSON.stringify(this.data)}

      <div
        @click=${() => this.close()}
        style="cursor:pointer; padding: 20px; background-color: blue"
      >
        Close
      </div>
    `;
  }
})
export class TestModal extends LitElement {
  @Injector(MODAL_DIALOG_DATA)
  private data: { omg: string };

  @Inject(ModalService)
  private modalService: ModalService;

  private modalRef = this.modalService.getRef();

  OnInit() {
    console.log('test-modal initialized');
  }
  OnDestroy() {
    console.log('test-modal destroyed');
  }

  close() {
    this.modalService.close();
  }
}

/* Modal View Component */
@Component({
  selector: 'modal-view-component',
  template(this: ModalViewComponent) {
    return html`
      <div
        @click=${() => this.openAdvancedModal()}
        style="cursor:pointer; padding: 20px; background-color: blue"
      >
        Open Advanced Modal
      </div>
    `;
  }
})
export class ModalViewComponent extends LitElement {
  @Inject(ModalService)
  private modalService: ModalService;

  openAdvancedModal() {
    this.modalService.openComponent(TestModal, { omg: 'dada' });
  }
}
Using it to spawn Wizards or Sequence of modals
import { Component, LitElement, html, css } from '@rxdi/lit-html';
import { Inject, Injector } from '@rxdi/core';
import { ModalService } from '@rxdi/ui-kit/modal/modal.service';
import { MODAL_DIALOG_DATA } from '@rxdi/ui-kit/modal/interface';
import { of } from 'rxjs';
import { switchMap } from 'rxjs/operators';


/* TestModal Component */
@Component({
  selector: 'test-modal',
  template(this: TestModal) {
    return html`
      Test Modal ${JSON.stringify(this.data)}

      <div
        @click=${() => this.close()}
        style="cursor:pointer; padding: 20px;position: absolute; bottom: 0; right: 0"
      >
        Close
      </div>
    `;
  }
})
export class TestModal extends LitElement {
  @Injector(MODAL_DIALOG_DATA)
  private data: number;

  @Inject(ModalService)
  private modalService: ModalService;

  private modalRef = this.modalService.getRef();
  OnInit() {
    console.log('test-modal initialized');
  }
  OnDestroy() {
    console.log('test-modal destroyed');
  }

  close() {
    // debugger;
    this.modalService.close(this.data);
  }
}


/* Modal View Component */
@Component({
  selector: 'modal-view-component',
  style: css`
    .button {
      cursor: pointer;
      padding: 20px;
      margin: 20px;
      background-color: blue;
    }
    .button:hover {
      opacity: 0.9;
    }
  `,
  template(this: ModalViewComponent) {
    return html`
      <div @click=${() => this.startWizard()} class="button">
        Open Modal Sequence
      </div>
    `;
  }
})
export class ModalViewComponent extends LitElement {
  @Inject(ModalService)
  private modalService: ModalService;

  startWizard() {
    const data = Array(5)
      .fill(null)
      .map((_, i) => ({ component: TestModal, data: i }));
    of(data)
      .pipe(switchMap((v) => this.modalService.openSequence(v)))
      .subscribe(console.log);
  }

  closeModal() {
    this.modalService.close();
  }

}

Hacks

  OnInit() {
    const container = document.querySelector('modal-container');
    const content = container.shadowRoot.querySelector('.content');
    content.addEventListener('click', () => this.close());
  }
Modal service
import { Injectable, Inject } from '@rxdi/core';
import { html, css } from '@rxdi/lit-html';
import { ModalService } from '@rxdi/ui-kit/modal/modal.service';

@Injectable()
export class ModalViewService {
  @Inject(ModalService)
  private modalService: ModalService;

  openMainModal() {
    return this.modalService.openMainModal(
      {
        title: `Default`,
        description: `
          Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
          eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim
          ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
          aliquip ex ea commodo consequat. Duis aute irure dolor in
          reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
          pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
          culpa qui officia deserunt mollit anim id est laborum.
          `
      },
      { backdropClose: true }
    );
  }

  openBasicModal() {
    return this.modalService.open(
      html`
        <div
          @click=${() => this.modalService.close(false)}
          style="cursor:pointer; padding: 20px; background-color: blue"
        >
          Close Modal
        </div>
      `
    );
  }

  openCustomMainModal() {
    return this.modalService.openMainModal(
      {
        template: html`
          <div style="padding: 15px 30px;border-bottom: 1px solid #e5e5e5;">
            <h1>Custom modal</h1>
          </div>
          <div
            style="padding: 10px 30px 10px 30px; border-bottom: 1px solid #e5e5e5;"
          >
            <p>
              Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
              eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
              enim ad minim veniam, quis nostrud exercitation ullamco laboris
              nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in
              reprehenderit in voluptate velit esse cillum dolore eu fugiat
              nulla pariatur. Excepteur sint occaecat cupidatat non proident,
              sunt in culpa qui officia deserunt mollit anim id est laborum.
            </p>
          </div>
          <div style="text-align: right">
            <span @click=${() => this.modalService.close()}>Cancel</span>
            <span>Save</span>
          </div>
        `,
        style: css`
          .dialog {
            padding: 0 !important;
          }
        `
      },
      { backdropClose: false }
    );
  }

  openOverflowCustomModal() {
    return this.modalService.openMainModal(
      {
        template: html`
          <div style="padding: 15px 30px;border-bottom: 1px solid #e5e5e5;">
            <h1>Overflow</h1>
          </div>
          <div class="content">
            <p>
          Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
          eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim
          ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
          aliquip ex ea commodo consequat. Duis aute irure dolor in
          reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
          pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
          culpa qui officia deserunt mollit anim id est laborum.
          Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
          eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim
          ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
          aliquip ex ea commodo consequat. Duis aute irure dolor in
          reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
          pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
          culpa qui officia deserunt mollit anim id est laborum.
          Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
          eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim
          ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
          aliquip ex ea commodo consequat. Duis aute irure dolor in
          reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
          pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
          culpa qui officia deserunt mollit anim id est laborum.
          Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
          eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim
          ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
          aliquip ex ea commodo consequat. Duis aute irure dolor in
          reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
          pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
          culpa qui officia deserunt mollit anim id est laborum.
          Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
          eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim
          ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
          aliquip ex ea commodo consequat. Duis aute irure dolor in
          reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
          pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
          culpa qui officia deserunt mollit anim id est laborum.
          Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
          eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim
          ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
          aliquip ex ea commodo consequat. Duis aute irure dolor in
          reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
          pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
          culpa qui officia deserunt mollit anim id est laborum.
            </p>
          </div>
          <div style="text-align: right">
            <span @click=${() => this.modalService.close()}>Cancel</span>
            <span>Save</span>
          </div>
        `,
        style: css`
          .dialog {
            padding: 0 !important;
          }
          .content {
            padding: 10px 30px 10px 30px;
            border-bottom: 1px solid #e5e5e5;
            overflow: auto;
            min-height: 150px;
            max-height: 555px;
          }
        `
      },
      { backdropClose: true }
    );
  }

  openFullScreenModal() {
    return this.modalService.openMainModal(
      {
        template: html`
          <div class="flex-grid">
            <img src="https://getuikit.com/docs/images/photo.jpg" />
            <h1>Full-screen modal</h1>
          </div>
        `,
        style: css`
          .container {
            padding: 0px !important;
          }
          .flex-grid {
            display: flex;
            flex-wrap: wrap;
            margin: 0;
            padding: 0;
            list-style: none;
          }
          img {
            background-position: 50% 50%;
            background-repeat: no-repeat;
            width: 50%;
            min-height: calc(100vh);
            box-sizing: border-box;
            background-size: cover;
          }
          .dialog {
            padding: 0 !important;
            width: 100% !important;
            height: 100% !important;
          }

          .container {
            height: 100%;
          }
        `
      },
      { backdropClose: false }
    );
  }
}

@Stradivario Stradivario force-pushed the 7-modal-container-initialization branch 2 times, most recently from 9cbcc6c to b949720 Compare October 15, 2019 20:09
@Stradivario Stradivario force-pushed the 7-modal-container-initialization branch from b949720 to 6a20a55 Compare October 15, 2019 20:09
@Stradivario Stradivario force-pushed the 7-modal-container-initialization branch 7 times, most recently from 0b5c65b to dba6789 Compare October 16, 2019 16:04
…lities for adding injectable with data when using with web component directly
@Stradivario Stradivario force-pushed the 7-modal-container-initialization branch from dba6789 to 0d4a9d3 Compare October 16, 2019 16:28
@Stradivario Stradivario changed the title 7 modal container initialization component(ModalContainer): modal container initialization Oct 16, 2019
@Stradivario Stradivario force-pushed the 7-modal-container-initialization branch 4 times, most recently from b46248c to 13f7f92 Compare October 17, 2019 10:20
@Stradivario Stradivario force-pushed the 7-modal-container-initialization branch from 13f7f92 to 2c7b1f8 Compare October 17, 2019 10:23
@Stradivario Stradivario force-pushed the 7-modal-container-initialization branch 6 times, most recently from 77b9cf7 to d9f504c Compare October 17, 2019 12:30
…ameter representing options for current modal which is opened
@Stradivario Stradivario force-pushed the 7-modal-container-initialization branch 2 times, most recently from 262f268 to 968de2f Compare October 17, 2019 13:41
@Stradivario Stradivario force-pushed the 7-modal-container-initialization branch 8 times, most recently from 1fabb20 to e42029a Compare October 17, 2019 15:00
@Stradivario Stradivario force-pushed the 7-modal-container-initialization branch from e42029a to c653fbd Compare October 17, 2019 15:00
@Stradivario Stradivario force-pushed the 7-modal-container-initialization branch 2 times, most recently from 7e4f43d to 1d423b7 Compare October 17, 2019 20:12
@Stradivario Stradivario force-pushed the 7-modal-container-initialization branch from 1d423b7 to 32e23b7 Compare October 17, 2019 20:13
@Stradivario Stradivario force-pushed the 7-modal-container-initialization branch 5 times, most recently from 192b694 to d3f3165 Compare October 17, 2019 23:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant