/ember-link

Renderless component for creating links. It's {{link-to}}, but better!

Primary LanguageTypeScriptMIT LicenseMIT

ember-link

Build Status npm version Download Total Ember Observer Score code style: prettier
Dependabot enabled dependencies Status devDependencies Status

It's like {{link-to}}, but renderless!

Renderless / Container / Provider Components are components that don't emit any DOM, but only yield state and actions to nested components.

The idea for this component traces back to this EmberMap session: Using Functional CSS with Ember.

Installation

ember install ember-link

👉 This is an Ember Octane addon. For a version that is compatible with older versions of Ember check out the 0.x series.

Usage

<Link
  @route="some.route"
  @models={{array 123}}
  @query={{hash foo="bar"}}
as |l|>
  <a
    href={{l.href}}
    class={{if l.isActive "is-active"}}
    {{on "click" l.transitionTo}}
  >
    Click me
  </a>
</Link>

Arguments

@route

Required.

The target route name.

Example

<Link @route="some.route" as |l|>
  <a
    href={{l.href}}
    class={{if l.isActive "is-active"}}
    {{on "click" l.transitionTo}}
  >
    Click me
  </a>
</Link>

{{link-to}} equivalent

{{#link-to "some.route"}}
  Click me
{{/link-to}}

@models

Optional. Mutually exclusive with @model.

An array of models / dynamic segments.

Example

<Link @route="some.route" @models={{array someModel someNestedModel}} as |l|>
  <a
    href={{l.href}}
    class={{if l.isActive "is-active"}}
    {{on "click" l.transitionTo}}
  >
    Click me
  </a>
</Link>

{{link-to}} equivalent

{{#link-to "some.route" someModel someNestedModel}}
  Click me
{{/link-to}}

@model

Optional. Mutually exclusive with @models.

Shorthand for providing a single model / dynamic segment. The following two invocations are equivalent:

<Link @route="some.route" @model={{someModel}} />
<Link @route="some.route" @models={{array someModel}} />

@query

Optional.

Query Params object.

Example

<Link @route="some.route" @query={{hash foo="bar"}} as |l|>
  <a
    href={{l.href}}
    class={{if l.isActive "is-active"}}
    {{on "click" l.transitionTo}}
  >
    Click me
  </a>
</Link>

{{link-to}} equivalent

{{#link-to "some.route" (query-params foo="bar")}}
  Click me
{{/link-to}}

@preventDefault

Optional. Default: true

If enabled, the transitionTo and replaceWith actions will try to call event.preventDefault() on the first argument, if it is an event. This is an anti-foot-gun to make <Link> just work™️ with <a> and <button>, which would otherwise trigger a native browser navigation / form submission.

Yielded Parameters

href

string

The URL for this link that you can pass to an <a> tag as the href attribute.

<Link @route="some.route" as |l|>
  <a href={{l.href}} {{on "click" l.transitionTo}}>
    Click me
  </a>
</Link>

isActive

boolean

Whether this route is currently active, including potentially supplied models and query params.

In the following example, only one link will be is-active at any time.

<Link @route="some.route" @models={{array 123}} @query={{hash foo="bar"}} as |l|>
  <a
    href={{l.href}}
    class={{if l.isActive "is-active"}}
    {{on "click" l.transitionTo}}
  >
    One
  </a>
</Link>

<Link @route="some.route" @models={{array 123}} @query={{hash foo="quux"}} as |l|>
  <a
    href={{l.href}}
    class={{if l.isActive "is-active"}}
    {{on "click" l.transitionTo}}
  >
    Two
  </a>
</Link>

isActiveWithoutQueryParams

boolean

Whether this route is currently active, including potentially supplied models, but ignoring query params.

In the following example, the first two links will be is-active simultaneously.

<Link @route="some.route" @models={{array 123}} @query={{hash foo="bar"}} as |l|>
  <a
    href={{l.href}}
    class={{if l.isActiveWithoutQueryParams "is-active"}}
    {{on "click" l.transitionTo}}
  >
    One
  </a>
</Link>

<Link @route="some.route" @models={{array 123}} @query={{hash foo="quux"}} as |l|>
  <a
    href={{l.href}}
    class={{if l.isActiveWithoutQueryParams "is-active"}}
    {{on "click" l.transitionTo}}
  >
    Two
  </a>
</Link>

<Link @route="some.route" @models={{array 456}} @query={{hash foo="quux"}} as |l|>
  <a
    href={{l.href}}
    class={{if l.isActiveWithoutQueryParams "is-active"}}
    {{on "click" l.transitionTo}}
  >
    Three
  </a>
</Link>

isActiveWithoutModels

boolean

Whether this route is currently active, but ignoring models and query params.

In the following example, both links will be is-active simultaneously.

<Link @route="some.route" @models={{array 123}} @query={{hash foo="bar"}} as |l|>
  <a
    href={{l.href}}
    class={{if l.isActiveWithoutModels "is-active"}}
    {{on "click" l.transitionTo}}
  >
    One
  </a>
</Link>

<Link @route="some.route" @models={{array 456}} @query={{hash foo="quux"}} as |l|>
  <a
    href={{l.href}}
    class={{if l.isActiveWithoutModels "is-active"}}
    {{on "click" l.transitionTo}}
  >
    Two
  </a>
</Link>

transitionTo()

(event?: Event) => Transition

Transition into the target route.

If @preventDefault is enabled, also calls event.preventDefault().

replaceWith()

(event?: Event) => Transition

Transition into the target route while replacing the current URL, if possible.

If @preventDefault is enabled, also calls event.preventDefault().

Related RFCs / Projects