Ember.js: Durch Festlegen einer Controller-Eigenschaft in "setupController" wird der Abfrageparameter nicht aktualisiert

Erstellt am 21. Aug. 2014  ·  29Kommentare  ·  Quelle: emberjs/ember.js

Wenn Sie einen Controller definiert haben als

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

und im Routes setupController machst du so etwas wie ...

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

Der Abfrageparameter wird in der URL nicht festgelegt.

Sie können einen Arbeitsbereich hier sehen: http://emberjs.jsbin.com/dekuj/1/edit

Bug Inactive Query Params

Hilfreichster Kommentar

Auch ich sehe dieses Problem in Ember 2.11. Der Versuch, einen Abfrageparameter im Controller zu löschen, hat keine Auswirkung. Die Problemumgehung von @barelyknown bringt mich größtenteils dorthin, aber ich würde dies immer noch als offenen Fehler betrachten.

Alle 29 Kommentare

Behoben mit einem Ember.run.later (um sicherzustellen, dass die Dinge zuerst vollständig materialisiert wurden): http://emberjs.jsbin.com/kowoqo/1/edit

@machty - Was ist das erwartete Verhalten hier?

Ich dachte, wir hätten explizite Tests für diese ... Überprüfung.

Ich denke, das ist ein Fehler ... wir haben Tests dafür, aber nur im Zusammenhang mit einem transitionTo und nicht dem ersten Start der App.

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

Ich habe einen fehlgeschlagenen Test für diesen Fehler hinzugefügt: https://github.com/emberjs/ember.js/pull/5473
Ich werde versuchen, dies zu beheben

Ich glaube, ich bin auf ein verwandtes Problem gestoßen, daher bin ich mir nicht sicher, ob hier in GitHub ein separates Ticket erforderlich ist.

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'
            });
        }
    }
});

Dies funktioniert in allen Fällen außer beim Booten, wenn 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. ausgelöst wird

Kann mit Ember.run.next behoben werden

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

obwohl es sich falsch anfühlt.

JSBins:
Ohne Ember.run.next wird ein Fehler
Mit Ember.run.next wird 'redered' in der Konsole gedruckt

@ Igor10k Ich

Kann jemand bestätigen, dass dies in 1.8 immer noch ein Problem ist?

@wagenet ja das ist noch ein Problem in 1.8:
http://emberjs.jsbin.com/lezuhu/1/edit?html , js, Ausgabe

und Kanarienvogel:
http://emberjs.jsbin.com/doyohe/1/edit?html , js, Ausgabe

@machty - Gedanken?

Ich denke, dass dies auch für mich ein Fehler ist, wenn ich 1.8.1 verwende. Ich möchte jedes Mal, wenn sich ein bestimmtes queryParam ändert, eine spezielle Methode auf meinem Controller aufrufen. Ich habe einen Router, der ungefähr so ​​aussieht.
Irgendein Rat?

// ...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 - Ideen, wo man anfangen soll, sich damit zu beschäftigen?

Ich habe das gleiche Problem. this.set () im Controller aktualisiert die Abfrageparameter in der URL nicht

App.SearchController = Ember.Controller.extend ({
queryParams: ['domain'],
Domain: null,

domainField: Ember.computed.oneWay ('domain'),
Aktionen: {
searchSubmit: function () {
this.set ('domain', this.get ('domainField')); // Hiermit wird der Parameter 'domain' festgelegt, die URL wird jedoch nicht geändert. Das Modell in App.SearchRoute wird also nie wie erwartet aufgerufen
}}
},
});

App.SearchRoute = Ember.Route.extend ({
queryParams: {
Domain: {
refreshModel: true // Vollständigen Übergang aktivieren
},

},
Modell: Funktion (Parameter) {
var domain = params.queryParams.domain;

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

},
Aktionen: {
refresh: function () {
Ember.Logger.log ('Route wird jetzt aktualisiert ...');
this.refresh ();
}}
},
});

Können Sie bitte in der Zwischenzeit Abhilfe schaffen?

Zur Verdeutlichung: this.set () in meinem Code nimmt die Änderung am Class-Objekt vor, ändert jedoch die URL überhaupt nicht

Das ist uralt, aber es scheint immer noch ein Problem zu sein? Ich kann die Umstände nicht herausfinden, aber wenn ich regelmäßig versuche, einen Abfrageparameter vom Controller festzulegen, wird dieser nicht an die URL weitergegeben. Ich kann den Wert der Eigenschaft auf dem Controller überprüfen und sie ist korrekt festgelegt, aber die URL hat sich nicht geändert. Ich habe versucht, ein Ember.run.next ohne Erfolg zu verwenden. Weh!

Auch dieses Problem erleben

@rwjblue : Gibt es ein Update dazu?

Irgendein Update? Hier wird die URL auch beim Ändern des Werts vom Controller für einige ms aktualisiert und kehrt zum alten Wert zurück, selbst wenn der Controller den neuen Wert in der Variablen hat

Hier ist eine Problemumgehung:

Fügen Sie im Controller einen Beobachter hinzu, der den Abfrageparameter in der nächsten Ausführungsschleife ändert, nachdem er festgelegt wurde. In diesem Beispiel wollte ich den Abfrageparameter token aus der URL entfernen, und dieser Ansatz funktioniert gut.

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);
      });
    }
  }),
});

Ich bin heute darauf gestoßen, als ich versuchte, einen Abfrageparameter vom setupController beim Booten festzulegen. run.next scheint eine Problemumgehung zu sein, aber ich denke, die richtige Lösung wäre, zwei Routen zu haben, und beim Booten würde die erste Route mit dem Abfrageparameterwert zur zweiten Route übergehen.

Glut 2.8

Das Markierungsproblem ist gemäß unserer Triage-Richtlinie inaktiv.

Auch ich sehe dieses Problem in Ember 2.11. Der Versuch, einen Abfrageparameter im Controller zu löschen, hat keine Auswirkung. Die Problemumgehung von @barelyknown bringt mich größtenteils dorthin, aber ich würde dies immer noch als offenen Fehler betrachten.

EDIT: Ignoriere all diesen Jazz. Hier gibt es einige schlechte / falsche Informationen, und @locks hat mich auf eine viel bessere Lösung hingewiesen - mit einem Abfrageparameter anstelle eines dynamischen Segments - direkt darunter. Es bindet den Abfrageparameter an eine normale Eigenschaft mit einer Schattenberechnungseigenschaft, die bereinigt und auf get (meine vorherigen Versuche umfassten das Binden des Abfrageparameters an eine berechnete Eigenschaft, die bereinigt und auf set ). . Entschuldigung für den Lärm!


Die bessere Lösung ...

// 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);
    }
  })
});


Das ursprüngliche Problem und die Lösung ...

Ich habe den größten Teil von gestern durch dieses Problem verloren, das in der 2.14-Beta immer noch besteht. Mein Anwendungsfall besteht darin, einen Abfrageparameter zu bereinigen, der als Index für ein Ember.Array verwendet werden soll. Wenn es fehlerhaft ist (z. B. NaN oder eine Zeichenfolge) und / oder außerhalb der Grenzen liegt, sollte es einen Standardindex verwenden und die URL aktualisieren, um die Anpassung widerzuspiegeln (damit Ereignisse als Reaktion auf zukünftige Klicks entsprechend ausgelöst werden - ich kann dies weiter erläutern helfen, den Fall zu machen, dass dies nicht nur ein kosmetisches Problem ist).

Ich kann die Eigenschaft nicht von setupController() festlegen, da die URL nicht aktualisiert wird (wie in dieser Ausgabe beschrieben). Ich kann es nicht im nächsten Tick mit Ember.run setzen, da dies zu spät wirksam wird (dh ein ungültiger Index wäre bereits für den Zugriff auf das Array verwendet worden). Ich kann es nicht einmal festlegen und dann im nächsten Häkchen erneut festlegen, um die URL zu aktualisieren, da keine Eigenschaftsänderung vorliegt (oder zumindest ist dies vermutlich der Grund, warum es nicht funktioniert).

Ich kann keine berechnete Eigenschaft mit einem Desinfektions-Setter im Controller verwenden, da Sie einen Abfrageparameter nicht an eine berechnete Eigenschaft binden können. Ich kann keinen Beobachter für eine normale Eigenschaft verwenden, da Sie die beobachtete Eigenschaft nicht festlegen können. Ich kann mit Ember.run aufgrund des oben beschriebenen Problems keinen Beobachter verwenden.

Ich kann this.transitionTo({ queryParams: .. }) von setupController() oder dem beforeModel() Hook oder controller.transitionToRoute({ queryParams: .. }) von setupController() aufgrund von # 14606 und verwandten Problemen anrufen. Ich kann refreshModel für den Abfrageparameter nicht auf true da im model() -Hook andere Dinge passieren, die nicht wiederholt werden sollten, wenn sich dieser Abfrageparameter ändert.

Es ist klar, dass hier ein Zusammenhang von Schmerz besteht. Dieses Problem, Problem Nr. 14606 und die Einschränkung, dass ein Abfrageparameter nicht an eine berechnete Eigenschaft gebunden werden kann, ergeben zusammen eine ordentliche, frustrierende kleine Falle.

Hier ist meine Problemumgehung: Ich habe eine verschachtelte "Auswahl" -Route erstellt, die einfach den Abfrageparameter (oder - wie im folgenden Code - ein dynamisches Segment) verwendet, bereinigt und die Eigenschaft auf dem übergeordneten Controller festlegt. Wenn der bereinigte Index außerhalb der Grenzen liegt, wechselt er zur verschachtelten Indexroute, die wiederum zur verschachtelten Auswahlroute mit dem Standardindex übergeht. Die verschachtelten Routen haben keine Vorlagen oder Controller und die übergeordnete Route hat keinen Ausgang. Sie existieren ausschließlich zur Behandlung dieses Routing-Problems.

// 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 danke für das Update, das wir schließen werden. Habe ein schönes Wochenende!

@locks Wenn Sie möchten, öffnen Sie bitte ein Dokumentationsproblem erneut, um dies auf dem setupController zu vermerken (siehe die Hinweise in den Dropdown-Listen von @mwpastore als Beispiele.

@mwpastore Klingt so, als könnten wir einen Beitrag im Forum unter https://discuss.emberjs.com/ mit Ihrer Lösung veröffentlichen

Warten Sie, bis dieses Problem mit einer alternativen Lösung behoben wurde, um den gemeldeten Fehler zu umgehen. Bei dieser Lösung wird eine Eigenschaft in einem berechneten Getter festgelegt.

Ich bin gespannt, ob es ein Update dazu gibt.

Ich verwende Ember.run.next in Routes setupController

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen