Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ng-host #19119

Open
cedvdb opened this issue Sep 9, 2017 · 15 comments
Open

ng-host #19119

cedvdb opened this issue Sep 9, 2017 · 15 comments
Labels
area: core Issues related to the framework runtime core: host and host bindings feature: under consideration Feature request for which voting has completed and the request is now under consideration feature Issue that requests a new feature
Milestone

Comments

@cedvdb
Copy link

cedvdb commented Sep 9, 2017

Proposal

I'd like an <ng-host> that would act in a similar way as the :host css property. That would apply directives and classes to the host component. Related #8785

Current behavior

my-component.template.ts

<div>1</div>
<div>2</div>

Currently to apply a class flex to the host component one can

  1. use host in the component decorator (or @HostBinding);
  2. use a wrapping element
  3. apply the class on the host from the parent template.

All of which are suboptimal.

1. Host

@Component({
 //... 
host: { class : 'flex' }
})

(Same applies for @HostBinding()).
Class declarations belongs in my template. Directives don't work here

2. Wrapper

<div class="flex">
  <div>1</div>
  <div>2</div>
</div>

Adds an additional tag.

3. Defining in parent

<my-component class="flex">

Leaks implementation outside the component itself.

Expected behavior

<ng-host class="flex">
 <div>1</div>
 <div>2</div>
<ng-host>

result

  <my-component class="flex">
    <div>1</div>
   <div>2</div>
 </my-component>

Compiling wrong usages

1. multiple ng-host

<ng-host class="flex"><ng-host>
<ng-host class="flexEnd">
  <div>1</div>
  <div>2</div>
<ng-host>

2. Multiple ng-host nested

<ng-host class="flex">
    <ng-host class="flexEnd">
        <div>1</div>
        <div>2</div>
    <ng-host>
<ng-host>

3. ng-host not used as the topmost component

<div> 1
     <ng-host class="flex flexEnd"><ng-host>
</div>
<div>2</div>

solution 1

Strictly speaking it would make sens to have those be invalid.

solution 2

ng-host act as a strict link to the host. Meaning that the above scenarios would result, in all cases, in this

<my-component class="flex flexEnd">
  <div>1</div>
  <div>2</div>
</my-component>

Thus when the compiler finds a ng-host element it just links whatever it finds to the host. No matter where it's put. I find this a bit less intuitive but could be easier to implement.

solution 3

<li> <ng-host></ng-host> </li>

compiles to this

<li><my-component></my-component></li>
@IgorMinar IgorMinar added the area: core Issues related to the framework runtime label Sep 20, 2017
@chuckjaz chuckjaz added the feature Issue that requests a new feature label Oct 27, 2017
@yogibimbi
Copy link

yogibimbi commented Jan 17, 2018

great idea! Came here to this url because I was thinking of / googling for the same feature. Would give the View some more oomph and make at least event processing a lot easier.

@ngbot ngbot bot added this to the Backlog milestone Jan 23, 2018
@cedvdb
Copy link
Author

cedvdb commented Feb 1, 2018

The main reason I'd like to have this is because I like my html to be easily readable and as lean as possible.
Unfortunately you often have to have a ctnr element:

<div class="ctnr flex cercle">
 actual content here
</div>

Using @HostBinding is not as readable as you don't have all the view information you need just by looking at the template.

@trotyl
Copy link
Contributor

trotyl commented Mar 15, 2018

Made a pure lib implementation here, demo here.

But I don't see any value of the content projection support, it would only made children ordering less obvious.

@vladuionut
Copy link

great @trotyl but how can I use it for structural directives (ex ngIf )

@trotyl
Copy link
Contributor

trotyl commented Mar 15, 2018

@vladuionut No, you can't. There's not something can be done by a proxy renderer.

And that's not logical at all, the binding value are coming from component (instance) context, how could the binding work without instantiate component first?

@aaronfrost
Copy link
Contributor

I am sick of adding the following to my components in order to use the style classes that we use. I would really love an ng-host like option.

    @HostBinding('class.Flex')
    flex = true;
    @HostBinding('class.Flex-Direction-Columnn')
    flexDir = true;
    @HostBinding('class.Flex-1')
    flex1 = true;

In order to add classes to my component, this is what I have to do. ng-host would be much nicer.

@pkozlowski-opensource
Copy link
Member

pkozlowski-opensource commented Apr 10, 2019

I know that this is not exactly what people are asking for here but when ivy lands one will be able to add classes to host in a non-destructive way, ex.:

@Component({
 selector: '...'   
 host: { class : 'Flex Flex-Direction-Columnn Flex-1' },
 template: `...`
})
class MyComponent {
   ...
}

which is much nicer as compared to :

    @HostBinding('class.Flex')
    flex = true;
    @HostBinding('class.Flex-Direction-Columnn')
    flexDir = true;
    @HostBinding('class.Flex-1')
    flex1 = true;

@cedvdb
Copy link
Author

cedvdb commented Apr 12, 2019

@pkozlowski-opensource

You can already do that. Or is the "non-destructive" part of the sentence important here ? :p

@pkozlowski-opensource
Copy link
Member

Or is the "non-destructive" part of the sentence important here

"non-destructive" is the key part here - today doing host: { class : 'Flex Flex-Direction-Columnn Flex-1' } would wipe-out any classes set on a host element (directly or other directives) - ivy introduces merging of classes.

@trotyl
Copy link
Contributor

trotyl commented Apr 13, 2019

@pkozlowski-opensource Would it possible to have a property-way of non-binding non-event host attribute declaration? Even the StyleGuide is recommending always using property decorator for that.


EDIT: doesn't seem to be a big issue for class case as one can still use:

@HostBinding('class')
foo = {
  'Flex': true,
  'Flex-Direction-Column': true,
  'Flex-1': true,
}

@TheTomasJ
Copy link

I was about to open exactly same feature-request when i found this 7 year old thing. This would be very very useful, especially improving code readability.

@GregOnNet
Copy link

Hey there,

thank you for this great proposal.
Our team would love to use this, too, because it simplifies style-overrides for Components a lot.
Currently, we see workarounds such as additional input()-Bindings, aka. [styleClass], because using host-properties is not used much or is less known.

<ng-host></ng-host> seems to be a declarative way of manipulating the host-Element.

@GregOnNet
Copy link

GregOnNet commented May 23, 2024

Hi together,

here is an approach my team came up with to allow style overrides for a component using Tailwind.

  1. We define the base theme in a private property #classDefaults
  2. We define an input for class to get a handle of classes being provided by the developer that should override the #classDefaults
  3. We merge both class and #classDefaults using twMerge. Without twMerge style overrides are not applied securely due to ordering & CSS specificity rules being applied by the browser.
  4. We bind a computed named hostClass to the component-host.
import { Component, computed, input } from '@angular/core';
import { twMerge } from 'tailwind-merge';

@Component({
  selector: 'app-label',
  standalone: true,
  host: {
    '[class]': 'hostClass()',
  },
  template: `<ng-content></ng-content>`,
})
export class LabelComponent {
  #classDefaults = 'text-red-500';

  protected hostClass = computed(() =>
    twMerge(this.#classDefaults, this.class())
  );

  class = input<string>('');
}
<app-label class="text-green-500">Hello, there!</app-label> 
<!-- default text color "red" will be overriden by color "green" -->

Currently, this serves our needs, but having a mechanism like ng-host would simplify this process a lot. 🤗

@superamadeus
Copy link

Came to Angular's issues to propose almost exactly the same feature.

@baterja
Copy link

baterja commented Jun 23, 2024

I got Angular project but I'm a guy with React experience. Came here while looking for a way to get rid of those unnecessary extra top-level tags that are breaking my sibling/direct-child CSS selectors.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: core Issues related to the framework runtime core: host and host bindings feature: under consideration Feature request for which voting has completed and the request is now under consideration feature Issue that requests a new feature
Projects
None yet
Development

No branches or pull requests