Using Angular2 to bind HTML markup to a boolean flag and trigger a method when the flag is set

I'm currently developing a solution for Angular 2 Bootstrap Datepicker to automatically close when a user clicks outside of it.

My current approach involves tracking external clicks and updating a boolean flag as shown below:

@Component({
    selector: 'ngbd-datepicker-popup',
    templateUrl: 'app/component/datepicker/datepicker.html',
    host: {
        '(document:click)': 'handleClick($event)'
    }
})

export class NgbdDatepickerPopup {

    private showDatePicker: boolean = true;


    constructor(private elementRef: ElementRef) {}



    handleClick(event: any) {
        if (!this.elementRef.nativeElement.contains(event.target)) {
            this.showDatePicker = false;
        } 
    }

}

Although I can track the clicks and update the flag, I'm uncertain how to proceed in order to properly close the datepicker. The challenge lies in calling the close() method from the markup where the datepicker is declared.

Here's the annotated markup:

<form class="form-inline" bindToBooleanFlagHere="d.close()"> <!--if true, close the popup --!>
    <div class="form-group">
        <div class="input-group">
            <input type="text" style="z-index: 0;" readOnly class="form-control" placeholder="mm-dd-yyyy" firstDayOfWeek="1"
               name="dp" [(ngModel)]="date" (ngModelChange)="dateChange(date)" ngbDatepicker #d="ngbDatepicker"> <!-- datepicker declared here --!>
            <div *ngIf="!disableThis" class="input-group-addon" style="background-color: white; cursor: pointer" (click)="d.toggle()">
                <i class="glyphicon calendar"></i>
            </div>
        </div>
    </div>
</form>

In my HTML, the datepicker object is identified as d while external clicks are tracked in the TypeScript component. Once the boolean flag showDatePicker is set to false due to an external click, the markup needs to respond by invoking the d.close() method.

Answer №1

Workarounds for Angular2 Bootstrap Datepickers

It's a bit of a workaround, but the issue at hand stems from the lack of support for certain behaviors in Angular2 Bootstrap Datepickers.

Here's how I tackled it:

Initially, I had to duplicate the HTML markup based on a boolean flag.

<form class="form-inline" *ngIf="showDatePicker">
    <div class="form-group">
        <div class="input-group">
            <input type="text" style="z-index: 0;" readOnly class="form-control" placeholder="mm-dd-yyyy" firstDayOfWeek="1"
                   name="dp" [(ngModel)]="date" (ngModelChange)="dateChange(date)" ngbDatepicker #d="ngbDatepicker">
            <div *ngIf="date != null" class="input-group-addon" style="background-color: white; cursor: pointer" (click)="clearDate()"><i class="glyphicon remove"></i>
            </div>
            <div *ngIf="!disableThis" class="input-group-addon" style="background-color: white; cursor: pointer" (click)="d.toggle()">
                <i class="glyphicon calendar"></i>
            </div>
            <div *ngIf="disableThis" class="input-group-addon" style="background-color: white; cursor: pointer">
                <i class="glyphicon calendar"></i>
            </div>
        </div>
    </div>
</form>
<form *ngIf="!showDatePicker" class="form-inline" (mousemove)="d.close(); resetShowDatePicker();">
    <div class="form-group">
        <div class="input-group">
            <input type="text" style="z-index: 0;" readOnly class="form-control" placeholder="mm-dd-yyyy" firstDayOfWeek="1"
                   name="dp" [(ngModel)]="date" (ngModelChange)="dateChange(date)" ngbDatepicker #d="ngbDatepicker">
            <div *ngIf="date != null" class="input-group-addon" style="background-color: white; cursor: pointer" (click)="clearDate()">
                <i class="glyphicon remove"></i>
            </div>
            <div *ngIf="!disableThis" class="input-group-addon" style="background-color: white; cursor: pointer" (click)="d.toggle()">
                <i class="glyphicon calendar"></i>
            </div>
            <div *ngIf="disableThis" class="input-group-addon" style="background-color: white; cursor: pointer">
                <i class="glyphicon calendar"></i>
            </div>
        </div>
    </div>
</form>

When the showDatePicker is false, I trigger the close function on mousemove, creating the illusion that the datepicker closes upon clicking. Then, the flag is reset to true seamlessly reopening the datepicker.

As for the component code:

handleClick(event: any) {
    if (this.elementRef.nativeElement.parentElement.contains(event.target) ||
        event.target.className === 'glyphicon calendar') {
        this.showDatePicker = true;
    } else {
        this.showDatePicker = false;
    }
}

resetShowDatePicker(): void {
    this.showDatePicker = true;
}

Answer №2

To close the component, obtain a reference to it and then execute the close function.

@ViewChild(NgbdDatePicker) modal:NgbdDatepickerModal;

handleButtonClick() {
  if (!this.elementRef.nativeElement.contains(event.target)) {
     this.modal.close();
  } 
}

I'm unsure about the accuracy of the @ViewChild() declaration as I may not have a full grasp of your code structure.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Having trouble locating a module while implementing lazy loading in an Angular project

I've managed to set up an Angular project successfully on a Mac environment. Angular CLI: 7.0.5 Node: 8.11.3 OS: darwin x64 Angular: 7.0.3 Now, I'm attempting to run the same code on Ubuntu 18.04 with the following setup: Angular CLI: 7.3.9 No ...

The integration of Angular and Node API within the IISNode directory structure is experiencing functionality issues

Read more about the question I have successfully set up my Node API and Angular component with IISnode. However, when accessing the application from the IIS server, I noticed that they are showing in different directories (see image below). Additionally, I ...

I am experiencing a discrepancy between the content of my DOM and what is actually displayed on the page while using Angular2 for heavy computation along with a loader show/h

In my current Angular 2 project, I am attempting to display a loader before performing a complex computation and then hiding it once the computation is complete. However, despite updating the DOM to show the loader, the view is not refreshing which results ...

Adjust the starting color of a mat-input in Angular 9

I am encountering an issue with the styling of a standard matInput field within a mat-form-field, all contained within a [formGroup] div. The dark background of the parent element is causing visibility problems with the default dark text color of the input ...

An issue was encountered during the prerendering of the page "/". For more information on this error, visit: https://nextjs.org/docs/messages/prerender-error Attempting to adjust the request (unable to determine

It's been four days and I'm still stuck. I've seen some suggestions to use axios and set the timeout or switch from HTTP to HTTPS when fetching data, but nothing has worked. I'm now four days behind deadline and the client is not going ...

Changing the text color of mat-chips in Angular Material

Having a mat-chip-set and multiple mat-chip elements with a custom product-chip class: <mat-chip-set> <mat-chip class="product-chip" *ngFor="let category of categories"> {{category}} </mat-chip> </mat-chip-s ...

There was a TypeScript error found at line 313, character 9 in the file @mui/material/styles/experimental_extendTheme.d

Encountering Typescript error while using Material UI component for date range picker Link - https://mui.com/x/react-date-pickers/date-range-picker/ Snippet of the code import * as React from 'react'; import { Dayjs } from 'dayjs'; im ...

Having trouble with debugging in Visual Studio for TypeScript (specifically Angular) projects? If Visual Studio 2017 is skipping over your breakpoints

// ============================== see updates below ============================== // While attempting to debug a TypeScript application in Visual Studio 2017 (NOT Visual Studio Code), I encountered an issue where inserting a breakpoint on a .ts file resu ...

What causes the discrepancy in results between these two NodeJS/Typescript imports?

Within my NodeJS project, I have integrated typescript version 3.2 alongside express version 4.16 and @types/express version 4.16. My development is focused on using Typescript with the intention of transpiling it later on. The guidelines for @types/expre ...

Customize your Kendo Chart in Angular2 by selecting the axis for your data

I need help creating a scatter chart with two separate datasets that have different Y-Axis How can I make sure the second series uses the second Y-Axis in the chart? <kendo-chart [title]="" style="height:290px"> <kendo-chart-series> < ...

Is it feasible to use Angular 2 in conjunction with local storage and JWT implementation on IE9 and

Could someone please advise me on how to implement local storage in Angular2 for IE9 and above? I've attempted following this guide https://medium.com/@blacksonic86/angular-2-authentication-revisited-611bf7373bf9#.h42z63t9v, but my Angular 2 applicati ...

Tips for extracting the value of T from a Promise<T>

I have a scenario where an async function is declared with a return type as follows: async function getNumber() { const {number} = await API_getNumber(); return number; } export type Return = ReturnType<typeof getNumber> In this case, Return ...

Prevent a specific file from being compiled during karma testing sessions

For my Angular application using angular-cli with Karma, I am facing an issue where a specific file needs to be excluded from compilation during unit tests. The file causing the problem is mentioned in the error message, indicating that it cannot be compi ...

Leveraging the 'styled()' utility from the MUI System while incorporating extra properties (Typescript)

I'm currently tackling a project using MUI System v5. I've opted to use the styled() utility (not styled-components) for styling and creating basic UI components. TypeScript is being used in this project, but I am facing a number of challenges as ...

Looking to place a global filter outside the primeNG table component?

I am currently utilizing primeNG in my project and I have a need to incorporate a global filter. The challenge I am facing is that I must add this filter in a different component. These two components are deeply nested within other components. My approach ...

Building a comprehensive project using Prisma and Next.JS in TypeScript - encountering an issue where the props "Component" and "pageProps" are deemed invalid

I'm currently in the process of developing my very first full-stack application. In this project, I have chosen to use Next.js as my React framework and Prisma as my ORM for handling database access and migrations. Once I established the connection to ...

Examining function invocations within the callback function of a subscribe method

I am currently working on a test to check if a method has been called within the subscribe callback function. The method in question is as follows: save() { this.testService.upsert(this.test).subscribe(() => { this.testMethod(); }); } T ...

Tips for resolving Circular dependency issue in node.js?

While working on a post request, I encountered an issue with the code below: try{ const _id = await db.collection('UserInformation').insertOne(userObj); await db.collection('LoggedInUser').updateOne({ userId: _id }, { '$set&ap ...

Validation of Angular2 Forms

Objective is to compare two password fields to verify if they are the same: <form [ngFormModel]="myForm" (ngSubmit)="onSubmit(myForm.value)"> <ion-label floating>password</ion-label> <ion-input type="password" [ngFormControl]="pa ...

Understanding the concept of inconsistent return points in Typescript: What implications does it carry?

I am currently working on converting a NodeJs JavaScript code to TypeScript. The code snippet below shows how I save uploaded files using JavaScript and now I'm encountering an error when trying to do the same in TypeScript. The error message says "Fu ...