Accessing attributes of a parent class object from within a child object

Imagine having four tabs within an Angular component, each with its own set of criteria for being displayed. Here's a high-level overview of the scenario.

export class DisplayTabs {
  foo: true;
  bar: false;
  tabs: {
    'A': { order: 1, get isVisible() { return this.foo; } },
    'B': { order: 2, get isVisible() { return !this.bar; } },
    'C': { order: 3, get isVisible() { return this.foo && this.bar; } },
    'D': { order: 4, get isVisible() { return !this.foo || this.bar; } }
  };
};

The current setup encounters an issue where this points to the tabs object rather than the encompassing DisplayTabs object. However, the decision on displaying the tabs relies on the properties of the DisplayTabs object itself.

I have considered structuring my tabs in a more organized and maintainable manner by defining them directly inside the DisplayTabs as follows:

export class DisplayTabs {
  foo: true;
  bar: false;
  get isTabAVisible() { return this.foo; }
  get isTabBVisible() { return !this.bar; }
  // etc.

Is there a way to reorganize this structure to achieve the desired outcome?

Answer №1

When faced with a situation where the natural approach clashes with the programming paradigm, it is crucial to reassess whether the correct paradigm is being used. In such cases, either the approach should be modified to align with the paradigm, or a different paradigm that complements the approach should be chosen. Consider this alternative solution:

type TabState = {
  foo: boolean
  bar: boolean
}

const state: TabState = {
  foo: true,
  bar: false,
}

enum TabOrder {
  A,
  B,
  C,
  D,
}

type Tab = {
  order: TabOrder
}

const isVisible = ({ foo, bar }: TabState, tab: Tab): boolean => {
  switch (tab.order) {
    case TabOrder.A: return foo;
    case TabOrder.B: return bar;
    case TabOrder.C: return foo && bar;
    case TabOrder.D: return !foo || bar;
  }
}

Playground

This approach is simpler to test (being a pure function dependent only on its arguments), well-typed, easier to debug, and so forth. While conventional wisdom may suggest that object-oriented programming is ideal for UI tasks, it's important to recognize that this isn't always the best fit. Even if you're constrained by an OO-centric framework or existing codebase, you can still encapsulate this functionality as a static method within a class.

Answer №2

At the beginning, you're defining a class but then switching to an object literal syntax. This can cause confusion as a class is not an object but rather a set of instructions for creating an object.

If we correct the syntax of your initial snippet, it will appear like this:

export class View {
    foo = true
    bar = false
    tabs = {
      'A': { order: 1, get isVisible() { return this.foo; } },
      'B': { order: 2, get isVisible() { return !this.bar; } },
      'C': { order: 3, get isVisible() { return this.foo && this.bar; } },
      'D': { order: 4, get isVisible() { return !this.foo || this.bar; } }
    }
  };

After making that correction, we can then implement an explicit constructor to access the object being constructed and use it within the methods:

export class View {
    foo = true
    bar = false
    tabs

    constructor() {
      const _this = this;
      this.tabs = {
        'A': { order: 1, get isVisible() { return _this.foo; } },
        'B': { order: 2, get isVisible() { return !_this.bar; } },
        'C': { order: 3, get isVisible() { return _this.foo && _this.bar; } },
        'D': { order: 4, get isVisible() { return !_this.foo || _this.bar; } }
      }
    }
  };

By creating an object instance with new View(), the methods within the tabs field will refer to the properties of the newly created object.

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

What is the process of creating a for loop in FindById and then sending a response with Mongoose?

Is there a way to get all the data in one go after the for loop is completed and store it in the database? The code currently receives user object id values through req.body. If the server receives 3 id values, it should respond with 3 sets of data to th ...

Retrieve the values of private variables within a defined function

While experimenting with typescript, I have encountered an issue that I can't seem to resolve. My project involves using Angular, so I will present my problem within that context. Here is a snippet of my code: class PersonCtrl{ private $scope: I ...

Typescript feature: Configuring BaseUrl with nested directories

When utilizing the 'baseUrl' property along with the 'paths' property in this manner: "baseUrl": "./src", "paths": { "app-component": [ "app/app.component"], "test-component": [ "app/test/test.component" ] } the compilation proces ...

Learn the proper way to specify the return type of a function as a class, rather than an instance, in Typescript

Is there a way to declare that a function returns a generic class definition? I have tried the following for non-generic classes, but it does not work for generic ones: export function composeAll(composeFunction: Function, depsFunction: Function): (compon ...

What is the best way to trigger a useReducer dispatch function from a different file that is not a React component, without relying on Redux?

In my project, I have a function component that shows a game board named "EnemyBoardComponent.tsx" const enemyBoardReducer = (state:number[][], action:Action)=>{ switch(action.type){ case "update": { return EnemyBoard.getGrid(); ...

When I refresh the page in Angular2, the router parameters do not get loaded again

When loading my application on routers without parameters, everything is normal. However, when trying to use a router with params, the application fails to load. For example: localhost:3000/usersid/:id The code for the router is as follows: const appRou ...

Is there a way to check for keys in a TypeScript object that I am not familiar with?

I have a good understanding of the unknown type in TypeScript. I am dealing with untrusted input that is typed as unknown, and my goal is to verify if it contains a truthy value under the key input.things.0. function checkGreatness(input: unknown) { retu ...

Errors during TypeScript compilation in Twilio Functions

When I run npx tsc, I encounter the following errors: node_modules/@twilio-labs/serverless-runtime-types/types.d.ts:5:10 - error TS2305: Module '"twilio/lib/rest/Twilio"' does not export 'TwilioClientOptions'. 5 import { Twil ...

The argument type 'MouseEvent<HTMLButtonElement, MouseEvent>' cannot be assigned to the parameter type 'HTMLElementEvent<HTMLButton>'

Here is the code snippet that I am currently working on and encountering an error in the console: type HTMLElementEvent<T extends HTMLElement> = Event & { target: T; } toggleHandler = (e: HTMLElementEvent<HTMLButtonElement>) => ...

Incorporate a personalized add-button into the material-table interface

My current setup includes a basic material-table structured like this: <MaterialTable options={myOptions} title="MyTitle" columns={state.columns} data={state.data} tableRef={tableRef} // Not functioning properly editabl ...

I am facing an issue with Nestjs where it is unable to resolve my dependency, despite the fact that it is readily available within the

Encountering the following error: Error: Nest is unable to resolve dependencies of the CreateGroupTask (TaskQueueService, GroupsService, ?, GroupNotificationsService, GroupRepository, Logger). Please ensure that the argument dependency at index [2] is avai ...

HTMLElement addition assignment failing due to whitespace issues

My current challenge involves adding letters to a HTMLElement one by one, but I'm noticing that whitespace disappears in the process. Here's an example: let s = "f o o b a r"; let e = document.createElement('span'); for (let i ...

Is it possible to include multiple eventTypes in a single function call?

I have created a function in my service which looks like this: public refresh(area: string) { this.eventEmitter.emit({ area }); } The area parameter is used to update all child components when triggered by a click event in the parent. // Child Comp ...

What causes the lack of impact on lambda rendering speed despite integrating webpack?

Hey there, I've been working on implementing webpack for a project that involves microservices, Node.js, TypeScript, AWS, and AWS SAM. My main objectives are: Reduce the cold start time of lambda functions. Minimize security vulnerabilities by e ...

When employing GraphQL Apollo refetch with React, the update will extend to various other components as well

My current setup involves using react along with Apollo. I have implemented refetch in the ProgressBar component, which updates every 3 seconds. Interestingly, another component named MemoBox also utilizes refetch to update the screen at the same int ...

What is the process for passing information to a nested component structure with parent-child-child relationships?

I am facing an issue with three nested components (C1, C2, C3) where C2 is called within C1 and C3 is called within C2. My goal is to pass data from C1 to C3 using property binding. In the template of C1, I successfully bound a variable that I can access ...

What are some effective methods for troubleshooting Vue.js computed properties and templates?

I am facing challenges with debugging in Vue.js, especially when it comes to debugging computed properties or data values in templates. Currently, I am using the IIFE method for debugging as shown in : <h2 dir="auto"> {{(function(){debugger;let ...

Struggling to Decode Octet-stream Data in Angular 6 HttpClient: Encountering Parsing Failure with Error Prompt: "Failed to parse HTTP response for..."

Is there a way to make a non-JSON request to the server using Angular 6 HttpClient (@angular/common/http) in order to receive an Octet-stream? Below is the code I have tried: getFile(file: any) { let headers = new HttpHeaders({ 'Content-T ...

Utilizing Mongoose RefPath in NestJS to execute populate() operation

After registering my Schema with mongoose using Dynamic ref, I followed the documentation available at: https://mongoosejs.com/docs/populate.html#dynamic-ref @Schema({ collection: 'quotations' }) export class QuotationEntity { @Prop({ r ...

Access the array values by their respective keys in an object that is returned from a custom JavaScript file utilizing the Node.js file system

I recently came across a config file with a unique format, as shown below: define([], function () { return { productItems: { item1: ['Apple', 'Ball', 'Car'], item2: [&apo ...