Ember.js: la définition d'une propriété de contrôleur dans `setupController` ne met pas à jour le paramètre de requête

Créé le 21 août 2014  ·  29Commentaires  ·  Source: emberjs/ember.js

si vous avez un contrôleur défini comme

App.IndexController = Ember.Controller.extend({
  queryParams: ['foo'],
  foo: ''
});

et dans le setupController de Routes, vous faites quelque chose comme ...

setupController: function(controller, model){
  controller.set('model', model);
  controller.set('foo', 'bar'); // <-- setting this should update the query param
}

Le paramètre de requête n'est pas défini dans l'URL.

Vous pouvez voir un bac de travail ici: http://emberjs.jsbin.com/dekuj/1/edit

Bug Inactive Query Params

Commentaire le plus utile

Je vois aussi ce problème sur Ember 2.11, essayer d'effacer un paramètre de requête dans le contrôleur n'a aucun effet, la solution de contournement de @barelyknown m'amène la plupart du temps, mais je considérerais toujours cela comme un bogue ouvert.

Tous les 29 commentaires

Corrigé avec un Ember.run.later (pour s'assurer que les choses se sont complètement matérialisées en premier): http://emberjs.jsbin.com/kowoqo/1/edit

@machty - Quel est le comportement attendu ici?

Je pensais que nous avions des tests explicites pour cela ... vérifier.

Je pense que c'est un bogue ... nous avons des tests pour cela mais uniquement dans le contexte d'un transitionTo et non du démarrage initial de l'application.

travail: http://jsbin.com/mejeto/1#/about

J'ai ajouté un test d'échec pour ce bogue https://github.com/emberjs/ember.js/pull/5473
Essayera de tenter de résoudre ce problème

Je pense que je suis tombé sur un problème connexe, donc je ne suis pas sûr qu'il ait besoin d'un ticket séparé ici dans GitHub.

export default Ember.Controller.extend({
    queryParams: ['modal'],
    modal: null,
    handleModal: function () {
        this.send('openModal', this.get('modal'));
    }.observes('modal')
});
export default Ember.Route.extend({
    actions: {
        openModal: function (name) {
            return this.render(name, {
                into: 'application',
                outlet: 'modal'
            });
        }
    }
});

Cela fonctionne dans tous les cas à part le démarrage quand il lance Error while processing route: index Nothing handled the action 'openModal'. If you did handle the action, this error can be caused by returning true from an action handler in a controller, causing the action to bubble.

Peut être corrigé en utilisant Ember.run.next

handleModal: function () {
    Ember.run.next(this, function () {
        this.send('openModal', this.get('modal'));
    });
}.observes('modal')

même si cela ne va pas.

JSBins:
Sans Ember.run.next génère une erreur
Avec Ember.run.next imprime 'redered' dans la console

@ Igor10k Je rencontre exactement le même problème, modal et tout. L'envelopper dans Ember.run.next le corrige, mais cela me semble également mal.

Quelqu'un peut-il confirmer que c'est toujours un problème dans la version 1.8?

@wagenet oui c'est toujours un problème dans la 1.8:
http://emberjs.jsbin.com/lezuhu/1/edit?html , js, sortie

et canari:
http://emberjs.jsbin.com/doyohe/1/edit?html , js, sortie

@machty - Pensées?

Je pense que c'est aussi un bogue pour moi aussi en utilisant 1.8.1. Ce que je veux faire, c'est appeler une méthode spéciale sur mon contrôleur chaque fois qu'un queryParam spécifique change. J'ai un routeur qui ressemble à ceci.
Aucun conseil?

// ...snip...

// for pagination
queryParams: {
  offset: {
    refreshModel: true
  }
},

model: function(params) {
  // returns model
},

setupController: function(controller, model) {
  this._super(controller, model);
  controller.set('model', model);

  // Fetch results is a method that does a bunch work
  // sets up some filters, generates a promise, resolves that promise
  // and then sets some array data on the controller once promise resolves.
  // offset is a pagination feature which determines which specific results
  // are fetched. I would like to be able to call fetchResults everytime the
  // offset queryParam is changed. 
  Ember.run.later(function() {
    controller.sendAction('fetchResults');
  })
}

// ...snip...

@machty - Des idées sur où commencer à creuser là-dessus?

J'ai le même problème. this.set () dans le contrôleur ne mettra pas à jour le paramètre de requête dans l'URL

App.SearchController = Ember.Controller.extend ({
queryParams: ['domaine'],
domaine: nul,

domainField: Ember.computed.oneWay ('domaine'),
Actions: {
searchSubmit: function () {
this.set ('domaine', this.get ('domainField')); // Ceci définit le paramètre 'domain' mais ne modifie pas l'URL. Ainsi, le modèle dans App.SearchRoute n'est jamais appelé comme prévu
}
},
});

App.SearchRoute = Ember.Route.extend ({
queryParams: {
domaine: {
refreshModel: true // Activer la transition complète
},

},
modèle: fonction (paramètres) {
domaine var = params.queryParams.domain;

  return $.getJSON('/search?domain=usv.com&name=').then(function(resp){
  console.log(resp);
  return resp.data;
});

},
Actions: {
rafraichir: function () {
Ember.Logger.log ('La route se rafraîchit maintenant ...');
this.refresh ();
}
},
});

Pouvez-vous s'il vous plaît fournir un travail autour dans l'intervalle?

Pour clarifier: this.set () dans mon code apportera la modification à l'objet Class, mais ne change pas du tout l'URL

C'est ancien, mais il semble que ce soit toujours un problème? Je ne peux pas comprendre les circonstances, mais périodiquement, lorsque j'essaie de définir un paramètre de requête à partir du contrôleur, il ne se propage pas à l'URL. Je peux vérifier la valeur de la propriété sur le contrôleur et elle est correctement définie, mais l'URL n'a pas changé. J'ai essayé d'utiliser un Ember.run.next en vain. Malheur!

Vous rencontrez également ce problème

@rwjblue : Y a-t-il une mise à jour à ce sujet?

Toute mise à jour? Ici, même lors de la modification de la valeur du contrôleur, l'url se met à jour pendant quelques ms et elle revient à l'ancienne valeur, même si le contrôleur a la nouvelle valeur dans la variable

Voici une solution de contournement:

Dans le contrôleur, ajoutez un observateur qui modifie le paramètre de requête dans la prochaine boucle d'exécution une fois qu'il a été défini. Dans cet exemple, je voulais supprimer le paramètre de requête token de l'URL et cette approche fonctionne bien.

import Ember from 'ember';

export default Ember.Controller.extend({
  queryParams: ['token'],

  token: null,

  unsetToken: Ember.observer('token', function() {
    if (this.get('token')) {
      Ember.run.next(this, function() {
        this.set('token', null);
      });
    }
  }),
});

Je viens de rencontrer cela aujourd'hui, lorsque j'ai essayé de définir un paramètre de requête à partir du setupController au démarrage. run.next semble être une solution de contournement, mais je pense que la solution appropriée serait d'avoir 2 routes et au démarrage, la première route ferait la transition vers la deuxième route avec la valeur du paramètre de requête.

Ember 2.8

Marquer le problème comme inactif conformément à notre politique de triage .

Je vois aussi ce problème sur Ember 2.11, essayer d'effacer un paramètre de requête dans le contrôleur n'a aucun effet, la solution de contournement de @barelyknown m'amène la plupart du temps, mais je considérerais toujours cela comme un bogue ouvert.

EDIT: Ignorez tout ce jazz. Il y a des informations incorrectes / erronées ici, et @locks m'a orienté vers une bien meilleure solution - avec un paramètre de requête au lieu d'un segment dynamique - en ligne immédiatement en dessous. Il lie le paramètre de requête à une propriété normale avec une propriété calculée de l'ombre qui nettoie et définit sur get (mes tentatives précédentes impliquaient de lier le paramètre de requête à une propriété calculée qui a été nettoyée et définie sur set ) . Désolé pour le bruit!


La meilleure solution ...

// app/router.js
Router.map(function() {
  this.route('shop');
});

// app/routes/shop.js
export default Ember.Route.extend({
  queryParams: {
    _selectedItemIndex: {
      replace: true
    }
  }
});

// app/controllers/shop.js
import computed from 'ember-macro-helpers/computed';

export default Ember.Controller.extend({
  cart: Ember.service.inject(),

  queryParams: {
    _selectedItemIndex: 'i'
  },

  _selectedItemIndex: 0,

  selectedItemIndex: computed('_selectedItemIndex', {
    get(index) {
      const itemsLength = this.get('cart.items.length');

      if (isNaN(index) || index < 0 || index >= itemsLength) {
        index = 0;
      }

      return this.set('_selectedItemIndex', index);
    },

    set(index) {
      return this.set('_selectedItemIndex', index);
    }
  })
});


Le problème et la solution d'origine ...

J'ai perdu la majeure partie d'hier à cause de ce problème qui persiste encore dans la version 2.14-beta. Mon cas d'utilisation est de nettoyer un paramètre de requête à utiliser comme index dans un Ember.Array. S'il est mal formé (par exemple, NaN ou une chaîne) et / ou hors limites, il doit utiliser un index par défaut et mettre à jour l'URL pour refléter l'ajustement (afin que les événements en réponse aux clics futurs se déclenchent de manière appropriée - je peux l'expliquer plus loin aider à faire valoir qu'il ne s'agit pas simplement d'un problème cosmétique).

Je ne peux pas définir la propriété à partir de setupController() car elle ne met pas à jour l'URL (comme décrit dans ce problème). Je ne peux pas le définir dans le prochain tick en utilisant Ember.run car cela prendra effet trop tard (c'est-à-dire qu'un index invalide aurait déjà été utilisé pour accéder au tableau). Je ne peux pas le définir une fois, puis le définir à nouveau dans la coche suivante pour mettre à jour l'URL car il n'y a pas de changement de propriété (ou du moins c'est ce que je soupçonne est la raison pour laquelle cela ne fonctionne pas).

Je ne peux pas utiliser une propriété calculée avec un setter de nettoyage dans le contrôleur car vous ne pouvez pas lier un paramètre de requête à une propriété calculée. Je ne peux pas utiliser d'observateur sur une propriété normale car vous ne pouvez pas définir la propriété que vous observez. Je ne peux pas utiliser d'observateur avec Ember.run en raison du problème décrit ci-dessus.

Je ne peux pas appeler this.transitionTo({ queryParams: .. }) partir de setupController() ou le crochet beforeModel() ou controller.transitionToRoute({ queryParams: .. }) partir de setupController() raison de # 14606 et de problèmes connexes. Je ne peux pas définir refreshModel sur true pour le paramètre de requête car d'autres choses se produisent dans le hook model() qui ne doivent pas être répétées si ce paramètre de requête change.

Il y a clairement un lien de douleur ici. Ce problème, le numéro 14606, et la limitation de ne pas pouvoir lier un paramètre de requête à une propriété calculée se combinent tous pour créer un petit piège ordonné et frustrant.

Voici ma solution de contournement: j'ai créé une route "select" imbriquée qui prend simplement le paramètre de requête (ou - comme dans le code ci-dessous - un segment dynamique), l'assainit et définit la propriété sur son contrôleur parent. Si l'index nettoyé est hors limites, il passe à la route d'index imbriqué, qui à son tour revient à la route de sélection imbriquée avec l'index par défaut. Les routes imbriquées n'ont pas de modèles ou de contrôleurs et la route parent n'a pas de sortie; ils existent uniquement pour gérer ce problème de routage.

// app/router.js
Router.map(function() {
  this.route('shop', function() {
    this.route('index', { path: '/' });
    this.route('select', { path: '/:index' });
  });
});

// app/routes/shop.js
export default Ember.Route.extend({
  setupController(controller, model) {
    this._super(...arguments);

    // some logic to set up the cart service
  },

  model() {
    // fetch products to shop
  }
});

// app/controllers/shop.js
export default Ember.Controller.extend({
  cart: Ember.service.inject(),

  selectedItemIndex: 0,

  actions: {
    selectItem(index) {
      return this.replaceRoute('shop.select', index);
    }
  }
});

// app/routes/shop/index.js
export default Ember.Route.extend({
  beforeModel() {
    return this.replaceWith('shop.select', 0);
  }
});

// app/routes/shop/select.js
export default Ember.Route.extend({
  setupController(_, { index }) {
    this._super(...arguments);

    const
      parentController = this.controllerFor('shop'),
      itemsLength = parentController.get('cart.items.length');

    index = parseInt(index, 10);
    if (Number.isNaN(index) || index < 0 || index >= itemsLength) {
      return this.replaceWith('shop.index');
    }

    parentController.set('selectedItemIndex', index);
  },

  model: _ => _
});

@mwpastore merci pour la mise à jour, nous clôturerons cela. Passe un bon weekend!

@locks si vous voulez, veuillez rouvrir un problème de documentation pour le noter sur le setupController (voir les notes dans les menus déroulants de

@mwpastore On dirait que nous pourrions poursuivre avec un message sur le forum sur https://discuss.emberjs.com/ avec votre solution

Attendez que ce problème soit résolu avec une solution alternative pour contourner le bogue qu'il signale, et cette solution implique la définition d'une propriété dans un getter calculé?

Je suis curieux de savoir s'il y a une mise à jour à ce sujet.

J'utilise Ember.run.next intérieur de setupController Route

Cette page vous a été utile?
0 / 5 - 0 notes