Ember.js: Cannot pass hash helper to link-to (EmptyObject lacking hasOwnProperty)

Created on 29 Sep 2018  Â·  14Comments  Â·  Source: emberjs/ember.js

Sometimes a route can resolve with multiple records like so:

model() {
  const profile = ...;
  const user = ...;

  return RSVP.hash({
    profile,
    user,
  });
},

So then you'd think you could use link-to like so:

{{link-to 'My Profile' 'profiles.show' (hash user=user profile=profile)}}

This doesn't work because the hash helper returns EmptyObject and extractQueryParams tries to call .hasOwnProperty() on it, resulting in an error.

There's a workaround to this which involves using an action with transitionTo but it feels like a poor experience.

This is an issue I've had with Ember for years. What's the correct way to pass multiple records to link-to if not this?

I'm using ember-cli 3.0.2.


Edit: I've started using the following helper in place of hash as a workaround:

import { helper } from '@ember/component/helper';

export function plainObject(params, hash) {
  const object = {};
  // NOTE: `hash` is an `EmptyObject` so we convert to a POJO so that it can be
  // used with `link-to`.
  Object.keys(hash).forEach(k => object[k] = hash[k]);
  return object;
}

export default helper(plainObject);
Bug Good for New Contributors

All 14 comments

This doesn't work because the hash helper returns EmptyObject and extractQueryParams tries to call .hasOwnProperty() on it, resulting in an error.

This is a bug, we can (and should) totally fix this (swapping to ’queryParams’ in obj instead of obj.hasOwnProperty(‘queryParams')). Would you mind taking a crack at a PR?

Yep, I can take a look tomorrow.

@rwjblue it might be a few days before I can get to this.

I wouldn't mind giving this a go, Hacktoberfest and all that :) That's if you can't @mhluska.

@Parrryy go for it 😄

This doesn't work because the hash helper returns EmptyObject and extractQueryParams tries to call .hasOwnProperty() on it, resulting in an error.

This is a bug, we can (and should) totally fix this (swapping to ’queryParams’ in obj instead of obj.hasOwnProperty(‘queryParams')). Would you mind taking a crack at a PR?

where is this code?

packages/@ember/-internals/routing/lib/system/route.ts:2207:48:      if (!combinedQueryParameterConfiguration.hasOwnProperty(propName)) {
  packages/@ember/-internals/routing/lib/utils.ts:16:50:  if (possibleQueryParams && possibleQueryParams.hasOwnProperty('queryParams')) {
> packages/@ember/-internals/routing/lib/system/router.ts:1668:22:    if (!queryParams.hasOwnProperty(key)) {

@mhluska - I'm actually unable to reproduce the original issue, I wrote a test that _should_ have failed but didn't:

    ['@test [GH#17018] using `hash` helper for model']() {
      this.addTemplate('index', `{{link-to 'Post' 'post' (hash id="bar")}}`);
      this.addTemplate('post', 'Post: {{model.id}}');

      this.router.map(function() {
        this.route('post', { path: '/posts/:post_id' });
      });

      return this.visit('/')
        .then(() => {
          this.assertComponentElement(this.firstChild, {
            tagName: 'a',
            attrs: { href: '/posts/bar' },
            content: 'Post',
          });

          return this.click('a');
        })
        .then(() => {
          this.assertText('Post: bar');
        });
    }

@rwjblue maybe the issue here is that in (hash user=user profile=profile), user and profile are not ids but models. I'm not sure that this should be supported, since passing a model to link-to is already controversial.

The whole (hash ....) invocation is seen as a "model" from the {{link-to's perspective.

Isn't passing a record to link-to pretty standard? It should prevent the route from reloading data. That's the reason I want to pass two records via hash - to prevent reloading data.

@rwjblue that's strange. The only thing I can think of is maybe different versions than I was using?

Define standard...
It works right now but it's been decided that in general it's not a good pattern and in the future it might be no longer supported.

There was at least one RFC related to this, maybe more:
https://github.com/emberjs/rfcs/pull/283

@mhluska Are you able to create a test replicating the issue?

I am also not able to reproduce the issue and have written a test that replicates the scenario originally reported. The test passes — there are no issues retrieving the record passed to route via link-to hash.

https://github.com/emberjs/ember.js/pull/17769

If everything looks good with the test, I guess we can close this issue?

Yep, thank you @shawnren!

Was this page helpful?
0 / 5 - 0 ratings