23

I want to create a component that has attributes that need no value. For example, instead of something like this: (which I have now)

<app-document [mode]="'edit'" ... ></app-document>

or

<app-document [editMode]="true" ... ></app-document>

I would rather have:

<app-document editMode ...></app-document>

So the component itself has to see whether the attribute editMode is present or not. This will look a lot cleaner when I have a lot of such attributes. I haven't seen any documentation on how to do this. Is it doable?

3 Answers 3

38

Material2 wrote the following method:

/** Coerces a data-bound value (typically a string) to a boolean. */
export function coerceBooleanProperty(value: any): boolean {
  return value != null && `${value}` !== 'false';
}

Write something like that in your app-document component:

private _editMode: boolean;
@Input()
get editMode() { return this._editMode; }
set editMode(value: any) { this._editMode = coerceBooleanProperty(value); }

Then:

editMode == true
<app-document editMode></app-document>

editMode == false
<app-document></app-document>

If you use Material2 you can simply import the method as follows:

import {coerceBooleanProperty} from '@angular/cdk/coercion';
Sign up to request clarification or add additional context in comments.

Comments

8

You can use boolean @Inputs to achieve this.

HTML:

<app-document [editMode] ...></app-document>

TS:

export class AppDocumentComponent {
  @Input() editMode: boolean = true;
  // ...
}

Now you have a boolean which you can use to change your behavior.

note for better understanding:

The default value true kicks in, if there is a (valueless) attribute. If there is none, editMode does not get the default value but a falsy undefined. (So, that is why this works).

5 Comments

I didn't think of that pattern but that's pretty clever. If I'm not mistaken the value of editMode is the inverse (boolean not) of what is intuitive but I can live with that. Something like @Input('editMode') notEditMode: boolean = true;. Caffeine and monkeys seem to go together pretty well I guess.
This far simpler approach should have far more votes.
The problem with this solution is that <app-document editMode ...></app-document> results in editMode being false.
the problem also is that with @Input we need to use square brackets not really natural
" If there is none, editMode does not get the default value but a falsy undefined. (So, that is why this works)." This is not true, it will be true anyway
2

Updating the selected answer to use an input signal, you can now do the following:

import { input, booleanAttribute } from '@angular/core';
...
editMode = input(false, { transform: booleanAttribute } )

1 Comment

This should be the new accepted answer because if you don't use this transform as suggested an ESLint error is thrown: Type 'string' is not assignable to type 'boolean'.. I guess the default value of an input when you have no value is a string.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.