What is the best way to implement a custom NgbDateParserFormatter from angular-bootstrap in Angular 8?

Currently, I am working on customizing the appearance of dates in a form using Angular-Bootstrap's datepicker with NgbDateParserFormatter. The details can be found at here.

My goal is to display the date in the format of year-month-day in the form field and present it as day/month/year. To achieve this, I have implemented the following code in the component:

<...>
@Injectable()
export class CustomAdapter extends NgbDateAdapter<string> {

    readonly DELIMITER = '-';

    fromModel(value: string | null): NgbDateStruct | null {
        console.log('fromModel start', value);
        if (value) {
            let date = value.split(this.DELIMITER);
            return {
                day: parseInt(date[0], 10),
                month: parseInt(date[1], 10),
                year: parseInt(date[2], 10)
            };
        }
        return null;
    }

    toModel(date: NgbDateStruct | null): string | null {
        console.log('toModel start', date);
        let res: string = date ?
            date.year + this.DELIMITER + (date.month + '').padStart(2, "0") + this.DELIMITER + (date.day + '').padStart(2, "0")
            : null;
        console.log('toModel end', res);
        return res;
    }
}

@Injectable()
export class CustomDateParserFormatter extends NgbDateParserFormatter {

    readonly DELIMITER = '/';

    parse(value: string): NgbDateStruct | null {
        console.log('parser start', value);
        if (value) {
            let date = value.split(this.DELIMITER);
            console.log('parser end', date);
            return {
                day: parseInt(date[0], 10),
                month: parseInt(date[1], 10),
                year: parseInt(date[2], 10)
            };
        }
        return null;
    }

    format(date: NgbDateStruct | null): string {
        console.log('formatter start', date);
        let res: string = date ?
             (date.day + '').padStart(2, "0") + this.DELIMITER + (date.month + '').padStart(2, "0") + this.DELIMITER + date.year
            : null;
        console.log('formatter end', res);
        return res;
    }
}

@Component({
    <...>
    providers: [
        { provide: NgbDateAdapter, useClass: CustomAdapter },
        { provide: NgbDateParserFormatter, useClass: CustomDateParserFormatter }
    ]
})
export class MyComponent implements OnInit {
    myForm: FormGroup;
    <...>
    dpModel: any;

    constructor(
        <...>
        private ngbCalendar: NgbCalendar,
        private dateAdapter: NgbDateAdapter<string>
    ) {
        this.myForm = this.formBuilder.group({
            <...>
            date: [''],
            <...>
        });
    }

For template implementation:

<div class="form-group">
    <label for="data" class="col-form-label">Date:</label>
    <div class="input-group">
      <input class="form-control" placeholder="dd/mm/yyyy"
            name="data" [(ngModel)]="dpModel" 

            ngbDatepicker #d="ngbDatepicker" formControlName="data">
      <div class="input-group-append">
           <button class="btn btn-outline-secondary fa fa-calendar-alt" (click)="d.toggle()"></button>
      </div>
    </div>
</div>

After clicking on a date within the datepicker, these are the debug outputs from the code included:

toModel start NgbDate {year: 2020, month: 6, day: 18}
toModel end 2020-06-18
fromModel start 2020-06-18
formatter start null
formatter end null
toModel start null
toModel end null
fromModel start null
fromModel start 2020-06-18
In analyzing the output, there seems to be an issue where the component passes null to the formatter. Additionally, after selecting a date, a red line appears beneath the datepicker. I have experimented with different approaches like using myform.date instead of dpModel without success. I am currently utilizing Angular 8 for this project.

Answer №1

Instead

fromModel(value: string | null): NgbDateStruct | null {
    console.log('fromModel start', value);
    if (value) {
        let date = value.split(this.DELIMITER);
        return {
            day: parseInt(date[0], 10),
            month: parseInt(date[1], 10),
            year: parseInt(date[2], 10)
        };
    }
    return null;
}

recommend

fromModel(value: string | null): NgbDateStruct | null {
    if (value) {
        let date = value.split(this.DELIMITER);
        return {
            year: parseInt(date[0], 10),
            month: parseInt(date[1], 10),
            day: parseInt(date[2], 10)
        };
    }
    return null;
}

PS.: Keep in mind the year<->day switcharoo

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

EJS: Is there a way to display multiple populated collections from mongoose in EJS file?

Having trouble rendering multiple populated collections from mongoDB in EJS. To provide more context, I'll share snippets of my code: models, routes, and views. Model Schema var mongoose = require("mongoose"); var playerSchema = mongoose.Schema({ ...

What is the best way to use an Observable to interrogate a fork/join operation?

I have a forkjoin set up to check for the presence of a person in two different data stores. If the person is not found in either store, I want to perform a delete action which should return true if successful, and false otherwise. However, my current impl ...

What is the best way to create a Snap.svg map using AngularJS?

I am in the process of creating a web interface for an online board game. My goal is to load a Snap.svg map using Snap.load asynchronously. Once the map is loaded, I intend to attach a watch to a scope property and apply colors to the map based on that pr ...

Express JS encountering Firebase Google Sign-In glitch

Whenever a user clicks a button on the HTML page, this function is triggered. The function resides in auth.js and it is called from the server.js page. auth.js const firebase = require("firebase"); static googleSignIn(req,res){ firebase.aut ...

Implementing subscriber addition on Mailchimp 3.0 using Node.js and HTTPS

Here's the content of my app.js file: const express = require("express"); const bodyParser = require("body-parser"); const request = require("request"); const https = require("https"); const app = express(); app.use(express.static("public")); app.u ...

Getting a vnode from a DOM element in Vue 3.0: A Step-by-Step Guide

My question pertains to obtaining a vnode through accessing the DOM using document.getElementById(id). How can I accomplish this? ...

In a React application, the input field unexpectedly loses focus after typing just one character

Has anyone encountered an issue with a dropdown menu causing input field focus to be lost after typing one character? I've attempted setting unique keys for each field, but it hasn't resolved the problem. For reference, here is the link to the p ...

Can you include the dollar symbol in the currency format?

I currently have this code that formats numbers into currency format, however I would like to include the dollar sign ($) before the numbers. document.getElementById("numbers").onblur = function (){ this.value = parseFloat(this.value.r ...

Managing JSON data retrieval and manipulation with REST API in Node.js and MongoDB

My technology stack includes Node.js and MongoDB with a rest api. The input data I'm dealing with looks like this: var doc={"name":"ABX", duedate : new Date() } Before sending it to the server, I stringify the data: /rest/update?doc=JSON.s ...

Retrieve the generic type parameter of an interface implementation

I am attempting to extract a type parameter from an interface in order to use it as a parameter for a generic function. In my particular scenario, I have the following generic types: interface ITranslatable<T, K extends keyof T> { translations: IT ...

Javascript Google Maps API is not working properly when trying to load the Gmap via a Json

Trying to display a map using Gmaps and Jquery Ajax through JSON, but encountering difficulty in getting the map to appear on the page. The correct coordinates are being retrieved as confirmed by testing in the console. Puzzled by why it's not showin ...

Transferring PHP variables to Javascript variables

I'm working on a basic php script that updates specific elements of a game through JavaScript. I've encountered an issue where the variable data doesn't seem to transfer when passing them from the script to the game using forms. Currently, t ...

innerhtml does not display the entire array contents

I'm facing an issue with my innerHTML output where it seems to be displaying one less value than expected from the array. I've been unable to pinpoint the exact problem. await fetch(urlbody, bodyrequestOptions) .then((response) => response ...

Ways to check my component using ActivatedRoute?

I am currently facing an issue while testing a component that utilizes two resolvers (pagesResolver and UploadResolver): Below is the code snippet for my component: export class AdminPagesComponent implements OnInit { fileUploads$: Observable<FileUpl ...

How to determine the length of a JavaScript object

Would like help determining the length of the report_data(object) key using the provided code, but it seems to result in a value of 3. a={report_freq: "daily", report_item_num: 2, report_num: 39, report_data: "{}"} Object {report_freq: "daily", report_ite ...

Updating Angular JS views in real-time using database changes

I am currently in the process of building a social networking application using AngularJS. I have come across an issue regarding data binding. In my app, there is a timeline div where all the recent posts are displayed, along with a status updater at the t ...

Wrap it in a ReactJS container tag

Today I encountered a frustrating issue while diving into ReactJS. I'm excited to learn by getting my hands dirty, but unfortunately, I keep running into this error: Adjacent JSX elements must be wrapped in an enclosing tag (47:14) And here's t ...

Retrieve the identifiers of various HTML elements and store them in an array

Within a div, there are multiple objects. I am trying to retrieve the IDs of all elements based on their class, knowing that the number of elements may vary. So far, my attempt has been: arr = $(".listitem #checkBox").hasClass('checkedItem').att ...

including a code snippet within a dropdown menu or embedding it in a clickable button

Hey there, my name is Wouter Sanders and I am currently learning to code! I recently finished creating a RAL color picker for a project I'm working on. The only issue I've run into is trying to embed the code in a menu or button so that it doesn ...

Is it possible to pass parameters in the .env file in Node.js?

I am storing my file users.env inside routes/querys/users.env module.exports = { GET_USERS: "SELECT * FROM users", CREATE_USER: "INSERT INTO users ("id", "first_name", "last_name", "active") VALUES (NULL, '%PARAM1%', '%PARAM2%', & ...