Developing functions inside a class function in Typescript for Angular 2

Within my Angular 2 project, I have implemented bootbox.js to handle dialog creation such as alerts and confirmations. I am currently working on developing a dialog service but am facing challenges in structuring the Typescript code to enable me to use the service methods as intended.

The desired usage of my service:

export class SomeComponent {

  constructor(private _dialog: DialogService){}

  showConfirm() {
    _dialog.confirm()
      .title('Some title')
      .message('Some message')
      .okBtn('Sounds Good')
      .cancelBtn('No way!')
      .confirm(() => {})
      .cancel(() => {})
  }

showAlert() {
        _dialog.alert()
          .title('Some title')
          .message('Some message')
          .okBtn('Sounds Good')
          .callback(() => {})
      }

Current state of my service implementation:

export class DialogService {

confirm() {
    bootbox.dialog({
      title: title,
      message: message,
      buttons: {
        cancel: {
          label: cancelBtn,
          className: 'btn-inverse btn-inverse-primary',
          callback: () => cancel()
        },
        okay: {
          label: okBtn,
          className: 'btn-inverse btn-inverse-primary',
          callback: () => confirm()
        }
      }
    })
  }

 alert() {
    bootbox.dialog({
      title: title,
      message: message,
      buttons: {
        okay: {
          label: okBtn,
          className: 'btn-inverse btn-inverse-primary',
          callback: () => callback()
        }
      }
    })
  }

}

Ideally, I would like to pass parameters such as title and message from the component utilizing my service. However, I am unsure of how to structure the service to achieve this desired functionality.

Answer №1

If it’s clear to me, you’re seeking the builder pattern.

Below is an implementation based on your provided code snippet:

class DialogService {
    private _title: string;
    private _message: string;
    private _okBtn: string;
    private _cancelBtn: string;
    private _confirm: string;
    private _cancel: string;

    constructor() {}

    public title(value: string): DialogService {
        this._title = value;
        return this;
    }

    public message(value: string): DialogService {
        this._message = value;
        return this;
    }

    public okBtn(value: string): DialogService {
        this._okBtn = value;
        return this;
    }

    public cancelBtn(value: string): DialogService {
        this._cancelBtn = value;
        return this;
    }

    public confirm(value: () => {}): DialogService {
        this._confirm = value;
        return this;
    }

    public cancel(value: () => {}): DialogService {
        this._cancel = value;
        return this;
    }

    public show(): void {
        bootbox.dialog({
            title: this._title,
            message: this._message,
            buttons: {
                cancel: {
                    label: this._cancelBtn,
                    className: 'btn-inverse btn-inverse-primary',
                    callback: this._cancel
                },
                okay: {
                    label: okBtn,
                    className: 'btn-inverse btn-inverse-primary',
                    callback: this._confirm
                }
            }
        });
    }
}

Following that:

new DialogService()
    .title('Some title')
    .message('Some message')
    .okBtn('Sounds Good')
    .cancelBtn('No way!')
    .confirm(() => {})
    .cancel(() => {})
    .show();

Edit

I observed the modified question after my initial edit, so I am re-editing it:

interface ButtonData {
    label: string;
    className: string;
    callback: () => void;
}

class DialogService {
    private static BUTTON_CLASS_NAME = "btn-inverse btn-inverse-primary";

    private _title: string;
    private _message: string;
    private _okay: ButtonData;
    private _cancel: ButtonData;

    constructor() {}

    public title(value: string): DialogService {
        this._title = value;
        return this;
    }

    public message(value: string): DialogService {
        this._message = value;
        return this;
    }

    public okay(label: string, callback?: () => void): DialogService {
        this._okay = {
            label: label,
            className: DialogService.BUTTON_CLASS_NAME,
            callback: callback || function() {}
        };

        return this;
    }

    public cancel(label: string, callback?: () => void): DialogService {
        this._cancel = {
            label: label,
            className: DialogService.BUTTON_CLASS_NAME,
            callback: callback || function() {}
        };

        return this;
    }

    public alert(): void {
        bootbox.dialog({
            title: this._title,
            message: this._message,
            buttons: {
                okay: this.okay
            }
        });
    }

    public confirm(): void {
        bootbox.dialog({
            title: this._title,
            message: this._message,
            buttons: {
                cancel: this._cancel,
                okay: this.okay
            }
        });
    }
}

older edit

I’m still unsure about your specific requirements. I made some adjustments and included both `confirm` and `alert` methods, though their functionalities are not entirely clear...
The `confirm` method utilizes the existing `bootbox.dialog` from your code, but for the `alert`, I improvised with a `bootbox.alert` function.
This may not be accurate, so you might need to implement it as needed...

interface ButtonData {
    label: string;
    className: string;
    callback: () => void;
}

interface ServiceData {
    title: string;
    message: string;
    buttons: {
        cancel: ButtonData,
        okay: ButtonData
    };
}

class DialogService {
    private static BUTTON_CLASS_NAME = "btn-inverse btn-inverse-primary";
    private data: ServiceData

    constructor() {
        this.data = <ServiceData> {
            buttons: {
                cancel: <ButtonData> {},
                okay: <ButtonData> {}
            }
        };
    }

    public title(value: string): DialogService {
        this.data.title = value;
        return this;
    }

    public message(value: string): DialogService {
        this.data.message = value;
        return this;
    }

    public okay(label: string, callback?: () => void): DialogService {
        this.data.buttons.okay = {
            label: label,
            className: DialogService.BUTTON_CLASS_NAME,
            callback: callback || function() {}
        }

        return this;
    }

    public cancel(label: string, callback?: () => void): DialogService {
        this.data.buttons.cancel = {
            label: label,
            className: DialogService.BUTTON_CLASS_NAME,
            callback: callback || function() {}
        }

        return this;
    }

    public confirm(): void {
        bootbox.dialog(this.data);
    }

    public alert(): void {
        bootbox.alert(this.data);
    }
}

Answer №2

Consider implementing it this way:

export class CustomDialog {

public title: string;
public message: string;
.....  // other properties

confirm() {
    bootbox.dialog({
      title: title,
      message: message,
      buttons: {
        cancel: {
          label: cancelBtn,
          className: 'btn-inverse btn-inverse-primary',
          callback: () => cancel()
        },
        okay: {
          label: okBtn,
          className: 'btn-inverse btn-inverse-primary',
          callback: () => confirm()
        }
      }
    })
  }

}

Next, in the component using CustomDialog

export class AnotherComponent {

  constructor(private _customDialog: CustomDialog){}

  this._customDialog.title = 'Custom Title';
  this._customDialog.message = 'Message here';
  // more configuration

  this._customDialog.showConfirm();

}

This is one approach that could address your requirement. Hope this sheds some light!

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

Converting timestamp in Javascript to a human-readable date format

I am trying to convert a date retrieved from a MySQL database, which is in the format of 2015-09-14 17:15:24, to a more user-friendly format like 14 Sep, 2015 | 4:15 pm. I attempted to use the date.js JavaScript library but it didn't produce the desir ...

Issue with transmitting Razor form data to API controller using fetch or AJAX

I have created a basic razor web project and defined it as follows: in program.cs I added builder.Services.AddAntiforgery(o => o.HeaderName = "XSRF-TOKEN"); In the controller, this is what I did: [Route("/api/[controller]")] [ApiCon ...

What could be causing the prime factorization function to malfunction?

I have encountered an issue with a simple JavaScript function I created to factor down numbers into primes. The problem arises when the input number is the product of duplicate prime numbers, as the function does not include these duplicates in the array o ...

What is the process for assigning one array to another array in programming?

Check out this code snippet: export default class Application extends EventEmitter { constructor() { super(); this.config = config; this.data = { planets: [planetData] }; this.init(); let url; let count; let plane ...

Is there a way for me to retrieve a variable from within a .then function nested within another .then function?

Here is an example of code where I am attempting to log the value of 'a' to the console. driver.sleep(2000).then(function logAInConsole() { var a = ["Quas","Wex","Exort","Invoke"]; for(var i = 0; i < a.length; i++) { driver.sleep( ...

Is there a method to determine whether the user has granted permission for notifications to be enabled?

Once I have requested permission from the user of the website, I need to confirm if they have granted permission before triggering the send() function. What is the most sophisticated approach to achieve this? ...

Tips for maintaining position when refreshing a web page within a scrolling table

Recently, I came across a helpful tutorial on how to create a table with a fixed header and scrollable body. You can find it here. While the tutorial worked perfectly for me, I encountered an issue when trying to refresh the webpage and maintain my positio ...

What is the best way to test a React component that triggers a function in its parent, causing the component's props to be modified?

The issue at hand: The props of component Child are passed as the values of the state of Parent. Child contains a method that calls a method on Parent, which then updates the state of Parent. When Parent's state changes, one of Child's prop val ...

I'm experiencing an issue where the code I copy from jsfiddle does not function properly when pasted into notepad++

While browsing through the code on this page javascript countdown timer pause resume, I came across the following interesting snippet: var CountDown = (function ($) { // Length ms var TimeOut = 10000; // Interval ms var TimeGap = 1000; var CurrentTime = ...

How to identify and handle the invalid control within an Angular(v2 onwards) reactive form Form Array

When this.from.valid returns false, I utilize the following approach to identify the first invalid control and handle the error in my component. While this method works well for form groups without any form array, is there a way to identify the first inval ...

JavaScript: A guide to substituting specific characters in a string

I attempted to extract a list of names from a URL as URL parameters. var url_arrays = [],url_param; var url = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&'); for (var i = 0; i < url.length; i++) ...

Accessing an object within an array in a Node.js EJS file

Great job everyone! I've developed a project using Node.js which includes the following schema structure: const debt = new Schema({ name: { type: String, required: true, }, medicine: [{ data: { type: Schema.Types.ObjectId, ...

Using C++ with the Win32 API, is it possible to design a feature-rich and interactive HTML rendering window that will allow your application to receive callbacks from

What my team needs is straightforward: we are working on a console app project and we require a function that opens a basic window displaying only HTML (default system-based) with JavaScript rendering. This window should read a default HTML+JS string (ei ...

jQuery is not updating the div as expected

While typing out this question, I'm hoping to uncover a solution that has eluded me so far. However, just in case... About a year ago, I successfully implemented something similar on another website and went through the code meticulously. Surprisingl ...

The information in the map cannot be inferred by Typescript based on the generic key type

I encountered a TypeScript issue while refactoring an existing feature in my app. It seems that TypeScript is having trouble picking up the correct type when passing the generic type through nested functions. enum App { AppOne = 'app-one', A ...

Enhance the Material UI StepIcon by embedding real icons within the background circle

I have scoured through stack overflow but haven't come across a specific question addressing my issue. I am working on styling a Material UI Stepper component in a unique way. Most examples I've found use withStyles or makeStyles for color custom ...

Next.js is throwing an unhandled runtime error of type TypeError, which is causing issues with reading properties of null, specifically the 'default' property

"use client" import { useKindeBrowserClient } from '@kinde-oss/kinde-auth-nextjs' import Image from 'next/image'; import React from 'react' function DashboardHeader() { const {user} = useKindeBrowserClient(); r ...

Content in TinyMCE styled with the default CSS of the application

Hello fellow developers; I'm struggling to find a suitable solution to apply the same styles from our main CSS file to the text entered in the TinyMCE editor. Just to clarify, I don't want to alter the overall theme or appearance of TinyMCE itse ...

Ways to consistently display the vertical scroll bar on a mobile browser

Is there a way to always show the vertical scroll bar on mobile browsers, regardless of the page height? I've attempted using html {overflow-y: scroll;} which works well on desktop but not on mobile devices. Any suggestions or alternatives would be gr ...

Is there a way to make my siblings' elements turn black when hovering over an element?

Currently, I am working on CSS within Reactjs. In my project, I have two sibling elements: a logo and a text placed beside it. My goal is to have the text turn black when I hover over the logo, but so far, I have been unsuccessful in achieving this effect. ...