I'm trying to write a component to be reused across my application, which will sometimes show a control button and sometimes not.
Ideally, I'd want to get this from the presence or absence of an attribute, so that using the component would look something like <generic-component hideControls></generic-component>
, with a boolean variable in my component based on whether that attribute is present, but I can't see a way to do this.
Is there a way to do this?
I have tried with the slightly more messy version below (although ideally I would not need to set a value on showControls/hideControls);
generic.component.html
<div>
<div>Stuff</div>
<div *ngIf="showControls">Controls</div>
</div>
generic.component.ts
// imports etc.
@Component({
selector: 'generic-selector',
templateUrl: 'generic.component.html'
})
export class GenericComponent implements OnInit {
@Input()
public showControls: boolean = true;
// other inputs and logic
}
This fails, because the usage <generic-selector showControls="false"></generic-selector>
sets showControls as the string "false", which is truthy, rather than as the boolean value. So I have to get round it by adding a lot of mess to the component to take in the input and convert to a boolean based on whether it is being given the string "false" or not. A non-messy way to sort this would be appreciated, but I'd prefer being able to do the other option above.
@Inoput decorator is used to pass data (property binding) from parent to child component. The component property should be annotated with @Input decorator to act as input property. Let's explore it practically. I have created an angular application which is AngApp. I have created two components.
@Input() and @Output() give a child component a way to communicate with its parent component. @Input() lets a parent component update data in the child component. Conversely, @Output() lets the child send data to a parent component.
The boolean is a primitive type in Typescript. It represents a simple true/false value. They are implemented as numerical values with a single binary digit (i.e., 0 & 1). The Boolean is an object wrapper for the primitive boolean value.
This fails, because the usage
<generic-selector showControls="false"></generic-selector>
sets showControls as the string "false", which is truthy, rather than as the boolean value. So I have to get round it by adding a lot of mess to the component to take in the input and convert to a boolean based on whether it is being given the string "false" or not. A non-messy way to sort this would be appreciated, but I'd prefer being able to do the other option above.
using binding
<generic-selector [showControls]="false"></generic-selector>
You can use the Input
decorator as you would normally do with other attributes. The only trick is that when the attribute is non-present, the value would be undefined
, otherwise, the value would be an empty string.
Logic:
import { Component, OnInit } from '@angular/core';
@Component({
selector: '',
templateUrl: './boolean-component.component.html'
})
export class AppBooleanComponent implements OnInit {
@Input('boolean-attribute') booleanAttr: boolean;
ngOnInit() {
this.booleanAttr = this.booleanAttr !== undefined;
console.log(`Boolean attribute is ${this.booleanAttr ? '' : 'non-'}present!`);
}
}
Template 1 (logs 'Boolean attribute is present!'):
<app-boolean-component boolean-attribute></app-boolean-component>
Template 2 (logs 'Boolean attribute is non-present!'):
<app-boolean-component></app-boolean-component>
In Angular there are two ways to assign a value to your property:
In the first case, the value of your property will always be a string, like every HTML attribute even if you'll assign an interpolable string like this: {{true}}
.
While in the second case, it'll be interpreted as a JavaScript expression but in your context. So if you'll have an object notation there the value of your attribute will be the parsed as an object. But for specifying context angular is not using "with" statement so you can't use your globals there, but only the properties of the component in which scope your component is inserted.
<generic-selector [showControls]="false"></generic-selector>
In this case, it takes the string "false" and translates it to JavaScript.
So in JavaScript, it's a boolean, then you'll get it as a boolean
.
But if you'll have something like this:
<generic-selector [showControls]="{myProp: 'val'}"></generic-selector>
then the type of your showControls will be object
and its value will have myProp property equal to 'val'.
but if you'll have some nonliteral there then it'll be considered to be a property of your class:
<generic-selector [showControls]="location"></generic-selector>
then if you'll have a location property on the scope of the component containing your generic-selector
then the value of its location property will be taken otherwise it'll be undefined.
I'll suggest you to consider using ngOnInit for logging the property's type and the value assigned.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With