What is the best method to display a service property within a controller?

If we consider the scenario where I have a controller named ctrlA with a dependency called serviceB, which in turn has a property known as propertyC. My development environment involves Angular and Typescript. When interacting with the user interface, there is a need to show or hide certain HTML elements based on the value of this property.

There are different approaches that could be taken:

  1. I could create the service as a public variable and access it directly: <... ng-if="serviceB.propertyC">
  2. Alternatively, I could set up a property within the controller itself:

    public get exposedPropertyC(){    return this.serviceB.PropertyC;    }
    

This would allow me to access the property using: <... ng-if="exposedPropertyC">

The question arises - what is the correct way to go about achieving this functionality?

Answer №1

While I wouldn't classify it as strictly correct, the approach taken is more about consistency. Both methods are functional, but issues may arise due to inconsistencies in the responsibilities assigned to each component (which could also lead to testing complications).

The best practice would be to always expose a property through your controller. This ensures that each component maintains its designated responsibilities effectively. By adhering to this practice, your service can uphold its responsibilities with ease too.

@LoremIpsum mentioned a crucial issue in the comments: "your HTML not reaching stuff that's too far".

There are various scenarios related to this problem. Consider the following example with a controller named class MyController.

Direct access property

public exposedPropertyC: number;

constructor(private serviceB: ServiceB){
    this.serviceB = serviceB;
    this.exposedPropertyC = this.serviceB.PropertyC;
}

Async-acquired property

public exposedPropertyC: number;

constructor(private serviceB: ServiceB){
    this.serviceB = serviceB;
    this.serviceB.getPropertyC().then((propertyC) => {
        this.exposedPropertyC = propertyC;
    });
}

Observer pattern

In certain cases, implementing the observer pattern may seem like overkill, but it offers an efficient and elegant solution.

The code snippet below showcases a simple implementation of this pattern. While there are more advanced libraries available for TypeScript utilizing this pattern, this serves as a basic outline.

Disclaimer. The observer pattern is my go-to choice, despite appearing somewhat excessive. It provides flexibility and future-proofing for data retrieval optimizations from servers, enhancing maintainability and preventing potential headaches resulting from poor design decisions ;{D

interface ObservableCallBack<T> {
    (arg: T): void;
}

class Observable<T> {
    public yielded: T;
    public observers: ObservableCallBack<T>[];

    public subscribe(observableCallBack: ObservableCallBack<T>): void {
        this.observers.push(observableCallBack);
        if(this.yielded !== null) observableCallBack(this.yielded);
    }

    public notify(arg: T): void {
        this.yielded = arg;
        this.observers.forEach((observer) => {
            observer(arg);
        });
    }
}

class ServiceB {    
    public propertyC: Observable<number>;

    constructor(private http: IHttpService) {            
        this.propertyC = new Observable<number>();

        this.http.get('').then((res) => {
            this.propertyC.notify(res.data);
        });
    }
}

class MyController {    
    public propertyC: number;

    constructor(private serviceB: ServiceB) {
        this.serviceB.propertyC.subscribe((propertyC) => this.propertyC = propertyC);
    }
}

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

Learn the best way to retrieve the highest number from a Array<String> in TypeScript or JavaScript

Can someone help me create a function in JS or TS that meets the following requirements? I am looking for a functional programming approach. ・Input type: Array(String) ・Output type: string or undefined Examples Input Result ["" ...

Can you explain the functionality and process of scope.$new(true)?

I need assistance with testing a directive (more information available at: Unit testing angular directive - very stuck) I am particularly confused about the meaning of scope.$new(true). It seems like $new creates a new child scope, but I'm unsure abo ...

The property of userNm is undefined and cannot be set

When attempting to retrieve a value from the database and store it in a variable, an error is encountered: core.js:6014 ERROR Error: Uncaught (in promise): TypeError: Cannot set property 'userNm' of undefined TypeError: Cannot set property &apos ...

Retrieve the visible text content of an element by utilizing various ids

I am currently working on a project using AngularJS with multiple conditions all sharing the same id. My goal is to extract text only from the condition that evaluates to true. Recently, I discovered a major bug in an app that I am preparing for release. ...

Error in Typescript: The type 'Element' does not have a property named 'contains'

Hey there, I'm currently listening for a focus event on an HTML dialog and attempting to validate if the currently focused element is part of my "dialog" class. Check out the code snippet below: $(document).ready(() => { document.addEventListe ...

Angular Directive: A Guide to Crafting Custom Filters

Can someone explain why this Angular filter works when placed outside of an Angular directive but not inside? For example, in the Plunkr link provided below, I have inserted a search filter that functions correctly outside of the Bootstrap Angular UI acco ...

Transferring Data from JSON Object to an Array

In my AngularJS Controller, I have the following object: {"team":"1","name":"abc","age":"20"}, {"team":"1","name2":"def","age2":"21"}, {"team":"2","name":"ghi","age":"22"}, {"team":"2","name2":"jkl","age2":"23"}, I am looking to consolidate the items int ...

Filtering objects in AngularJS is a complex task, especially when you need to be able to search for a specific value but also consider if that value exists

Struggling to convey my thoughts in English, but here it goes. Imagine two objects linked by colorid: $scope.fruits = {{name:"apple",colorid:"1"},etc}; $scope.colors = {{id:"1",value:"red"}; I've created a table with search and filter function ...

Ways to retrieve the document ID or address in TypeScript when using Firestore

I am currently developing a function that will send notifications to all devices where a user is logged in whenever a new order document is added to their account. Below is the code I have written to execute this function. My main query revolves around ac ...

Rails: Parameters are displayed in the console but cannot be accessed via params

I sent a get request to the following url: groups/:id.json Upon checking my Rails server console, this is the output: Processing by GroupsController#show as JSON Parameters: {"id"=>"11"} However, despite these parameters being passed, I am unable t ...

When utilizing the ng-strict-di directive in AngularJS 1.3 with the ngbp framework, the application fails to load properly on the Chrome browser

I am currently developing a web application with AngularJS using the ngbp framework, previously known as ng-boilerplate. The default version of AngularJS in this framework is 1.2, but we are considering switching to 1.3 due to some appealing features it of ...

The AngularJS HTTP interceptor is a crucial component for handling

Is there a way to use an interceptor in AngularJS to log "finished AJAX request" when any request is completed? I've been exploring interceptors and currently have the following setup, but it triggers at the beginning of the request rather than the e ...

The http post request is functioning properly in postman, but it is not working within the ionic app

I am currently developing an app in ionic v3 within visual studio (Tools for Apache Cordova). On one of the screens in my app, I gather user information and send it to an API. However, I'm encountering an issue with the HTTP POST request that I'm ...

Typescript Tooltip for eCharts

I'm working on customizing the tooltip in eChart v5.0.2 using Typescript, but I'm encountering an error related to the formatter that I can't seem to resolve. The error message regarding the function keyword is as follows: Type '(param ...

Tips for saving an image that has been dragged onto the browser locally

I recently started working with Angular and decided to use the angular-file-upload project from GitHub here. I'm currently in the process of setting up the backend for my application, but I'd like to be able to display dropped files locally in th ...

Delete specific rows by clicking a button in AngularJS

I have a table with checkboxes for each row and I am trying remove the selected rows when a button is clicked. The selected row indexes are stored in an array using ng-change, but I cannot figure out how to delete them all at once with a single button clic ...

angular - what distinguishes between these two .factory functions?

sellingApp.factory('SellingService', ['$http', function ($http) { return { CheckStatus: CheckStatus }; function CheckStatus() { console.log(breeze); return $http({ method: 'GET' ...

The NestJS framework encountered an error due to a method being undefined in the

Encountering Error with NestJS Function create123: TypeError - Cannot read properties of undefined (reading 'create123') The constructor is displayed below \`export class AuthenticationService { constructor( private readonly usersServ ...

Creating a DynamoDB table and adding an item using CDK in Typescript

Can anyone guide me on how to add items to a Dynamodb Table using CDK and Typescript? I have figured out the partition/sort keys creation, but I am struggling to find a straightforward solution for adding items or attributes to those items. Additionally, ...

Using Typescript to specify the parameter type of a function as a generic function

After creating a function called compose, it looks like this: const composeTyped = <T, U, R>(f: (x: T) => U, g: (y: U) => R) => (x: T) => g(f(x)); It appears to me that both functions f and g fall under the type fGeneric, which is define ...