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

RFC: Yield link-to component state #275

Closed
wants to merge 2 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 126 additions & 0 deletions text/0000-link-to-yields.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
- Start Date: 2017-12-10
- RFC PR:
- Ember Issue:

# Summary

A proposal to allow the `link-to` helper to expose the active state via
`yield`. Doing so can allow more flexible use cases and DOM layouts.

# Motivation

`link-to` will add an `active` class to its element when the route matches.
However, many CSS frameworks or addons require a more specific layout where the
inner child needs the `active` class but the `onclick` event needs to be on the
parent link-to element. For example, Bootstrap CSS requires the child element to
have the `active` state to render correctly but the parent element must have the
`onclick` event handler otherwise the target area when rendered does not cover the
entire UI (due to margins/padding).

`link-to` also knows how to generate a URL (href) based on the route name.
Doing this conversion manually each time means the understanding of route name to
URL will be in multiple places in the app when instead could be calculated if
exposed by `link-to`.

# Detailed design

The syntax for `link-to` follows the convention of yielding to the consumer. It is
expected that clicking the `link-to` element will perform the route transition and
when the target route matches the current route the same element receives the
`active` class. The content of the element rendered to the DOM is often provided
by the consumer as yielded content.

```hbs
{{#link-to "my-route" tagName="li"}}
<a href="/hard/coded">Yielded Content</a>
{{/link-to}}
```

Which renders as:

```html
<li class="active">
<a href="/hard/coded">Yielded Content</a>
</li>
```

By yielding the active and href state we can leverage the `link-to` logic in the
context of our own code:

```hbs
{{! Example 1 }}
{{#link-to "my-route" tagName="li" as |link|}}
<a href={{link.href}} class="{{if link.active 'active'}}">My Route</a>
{{/link-to}}

{{! Example 2 }}
{{#link-to "my-route" tagName="li" as |link|}}
{{#if link.active}}
<span class="current-route red">Current Route</span>
{{else}}
<a href={{link.href}}>My Route</a>
{{/if}}
{{/link-to}}
```

# How We Teach This

The documentation for `link-to` will change the yield example to include a yielded
variable called `link` which will have two properties `link.active` and
`link.href`. A paragraph to explain that meaning of them and an example (see
above) to illustrate a possible use case.

Since this feature adds functionality to an existing API the current guides on
the link-to helper are enough as they are since it covers most use cases. When a
user needs more information (such as looking up `tagName` and `class`) via the
API section they can also discover the use of this feature.

This change would **not** modify how Ember is taught. It is backwards-compatible with current practices and typical usage out in the wild. The added
functionality need only documented once in the API for link-to.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have a Guide dedicated to link-to, where it would likely be warranted for the API in this RFC to be covered.


Most existing Ember users are familiar with the use of yielded variables and
adding this would not need much education beyond just letting them know it is
available via a ChangeLog and in the API documentation for the link-to component.

# Drawbacks

A tradeoff is that the two exposed values now become public. Which means it does
add the slight overhead to maintaining this part of the code since once made
public it will require more scrutiny before changing.

# Alternatives

This section could also include prior art, that is, how other frameworks in the
same domain have solved this problem.

Per this [Stack Overflow question][1] you can nest the link-to twice to cover
the specific Bootstrap problem. Unfortunately, it does not offer the flexibility
this feature allows for more advanced use cases.

The same [Stack Overflow question][1] also has a suggestion of wrapping the
link-to in a custom component which can investigate its DOM for active elements:

```js
export default Ember.Component.extend({
tagName: 'li',
classNameBindings: ['active'],
active: Ember.computed('[email protected]', {
get() {
return this.get('childViews').anyBy('active');
}
})
});
```

The disadvantage here is that the `onclick` handler is not on the parent element
and can cause styling problems if that requirement is needed. **This alternative
is no longer available since use of Glimmer.**

[1]: https://stackoverflow.com/questions/14328295/how-do-i-bind-to-the-active-class-of-a-link-using-the-new-ember-router

# Unresolved questions

1. What other drawbacks exist?
2. Are there other alternatives/workarounds that haven't been explored in
this RFC?
3. Which other use cases should be documented in this RFC?