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

Adding attributes to the component tag that is being generated by ui-router #3385

Closed
joerideg opened this issue Mar 24, 2017 · 14 comments
Closed

Comments

@joerideg
Copy link

joerideg commented Mar 24, 2017

Hello devs,

First of all, thanks for the awesome work on this repository! Keep it up!

I have the following problem:

  • I use UI router 1.0.0-rc1
  • I use the new component routing
  • I use Angular Material (1.1.3) layout functionality to layout my application
    When UI router routes to a component it automatically creates the component tag. eg <my-comp></my-comp> and nests it under the ui-view element. This all works great untill you combine it with a framework like Bootstrap or Angular Material that use classes to affect direct children of an element for layout.

For example the generated html output would be:

<my-app layout="row">
  <my-sidenav layout="column">
    <my-sidnav-list>
      ...
    </my-sidnav-list>
  </my-sidenav>

  <div ui-view layout="column">
    <my-component>
      <div id="childelement">
        ...
      </div>
    </my-component>
  </div>
</my-app>

With this output #childelement does not get the layout styling it needs because the tag is in between the layout element and the child element. I understand that this behavior is in fact correct. UI-view nests a component, a component nests its template, hence the result.

I could of course add styling to the component as a work around but what I really want is to be able to add attributes to the component tag that is being generated. That way I can easily use my layout framework in combination with ui router and components. Is this something that is possible and/or is it something that you are willing to add?

@joerideg joerideg changed the title Combining Component Routing with layout frameworks like Angular Material or Bootstrap Adding attributes to the component tag that is being generated by ui-router Mar 24, 2017
@christopherthielen
Copy link
Contributor

We already allow arbitrary templates to be used, i.e.:

template: '<my-component class="bootstrap-class"></my-component>

But you then obviously lose the route-to-component data bindings feature.

I think we could allow a callback which post-process the route-to-component template that ui-router builds.

We'd just need to decide on the best API, or how to leverage the existing APIs (template: or templateProvider: perhaps)

@joerideg
Copy link
Author

joerideg commented Mar 27, 2017

"But you then obviously lose the route-to-component data bindings feature."
Exactly!

Could it be as simple as a property 'componentAttributes' in the state definition that takes an object whos key value pairs get generated as attributes with respective values?

@ksamborn
Copy link

Hi - isn't this possible with the newly available bindings on the uiView (#3239)?

We are using this mechanism to pass parameters to the assigned components to the uiView (as well as the '&' bindings to inform it's parent.

here's what the generated HTML looks like:

<div ui-view="content" class="container-fluid">
    <my-container res1="::$resolve.res1">
        <div ui-view="SLOT" param="$ctrl.param">
            <my-component param="$ctrl.param" res1="::$resolve.res1" res2="::$resolve.res2">

The param is only coming from uiView and the res1 & res2 are resolves.

@elincognito
Copy link

elincognito commented Aug 3, 2017

This is also kinda of breaking my migration from template/controller to components.

I am being "forced" to do

template: '<states flex layout="column"></states>'

instead of a simple

component: 'states'

Because i need those attributes present on the parent container of my component html for it to render proper.

@fatore
Copy link

fatore commented Aug 17, 2017

@elincognito I'm facing the same issue here. I believe your suggestion to use template instead of component is the only way to do it for now.

I guess it would be interesting if the generated tag could inherit the attributes from the parent:

<ui-view flex layout="column"></ui-view>

@bitoverflow
Copy link

I ran into the same issue, where angular material requiring flex and layout attributes on every element child to make sticky toolbars work.

My workaround for now..

My ui-view is defined with <div ui-view flex layout="column">

On every completed state transation I manually add the classes normally added by the material attributes to the unreachable <ui-view> created by the router :

const element = document.getElementsByTagName('ui-view'); element[0].classList.add('flex'); element[0].classList.add('layout-column');

combined with defining state components in the state config
template: '<status-page layout="column" flex></status-page>'

Using: angular-material 1.1.5, ui-router 1.0.6

@peterpoe
Copy link

peterpoe commented Oct 3, 2017

Using this ugly-but-not-so-ugly workaround to add attributes required by my Angular Material layout.

First I add the resolves to the state definition:

resolve: {
  layout: () => 'column',
  layoutFill: () => true
}

Then the bindings to my component:

bindings: {
  layout: '@',
  layoutFill: '@'
}

Resulting template:

<my-component layout="column" layout-fill="true"></my-component>

@mmxcrono
Copy link

mmxcrono commented Feb 4, 2018

@peterpoe Very clever solution!

@joerideg
Copy link
Author

joerideg commented Feb 8, 2018

@peterpoe thanks thats a pretty smart way of going about it.

Still a documented api way that directly solves this problem would be nice. Any update on that, ui router devs?

@simonered
Copy link

simonered commented Apr 20, 2018

@peterpoe 's solution is a great workaround and it totally solves the problem! But, it's still a WORKAROUND... can you please provide an api way to do that? And it could be useful too having a way to apply that to all views, like a property for the $stateProvider instead of defining it for all states.

@simonemazzoni
Copy link

simonemazzoni commented May 25, 2018

Same problem with ui-router and angular material layout also for me.
Tried all the workaround but I still don't like them. It would be better to have a clean option param in state definition to accomplish that purpose.

@alejandroiglesias
Copy link

alejandroiglesias commented Dec 14, 2018

Using the template approach seems to break resolves update (resolves values that depend on dynamic params' values don't update when params change), and @peterpoe's solution doesn't seem to work with the class attribute, so a definitive fix is still needed for flexbox layouts.

@christopherthielen any chance of moving forward with the callback which post-process the route-to-component template that ui-router builds?

@AWilco
Copy link

AWilco commented May 27, 2019

My alternative workaround:

Knowing that there is only 1 child element to ui-view (the starting component), and that whatever the component is, I want to add these styles for layout, I created a custom CSS rule for it:

ui-view > * {
    flex-direction: column;
    flex: 1;
    display: flex;
    box-sizing: border-box;
}

This could be extended to apply only to certain components by specifying the component name in the rule
ui-view > myComponent {
or by adding/removing a class on ui-view as required.

@stale
Copy link

stale bot commented Jan 24, 2020

This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs.

This does not mean that the issue is invalid. Valid issues
may be reopened.

Thank you for your contributions.

@stale stale bot added the stale label Jan 24, 2020
@stale stale bot closed this as completed Feb 7, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests