jQuery Event Timming Problem (StateManager)

Hallo Shopware Community!

Ich möchte gerne ein Plugin entwickeln und bin an folgendes Problem gestossen.

Ich habe ein JavaScript hinzugefügt welches beim editieren eines Artikels verschiedene Werte berechnet unter anderem wird auch ein Dokument gespeichert und eine ID zum Dokument zurückgeliefert. Nun muss ich diese JavaScript variable irgendwie dem Cart zuweisen. Ich möchte im CheckoutController ajaxAddArticleCartAction den berechneten JavaScript wert speichern.

Also habe ich mir kurzerhand gedacht dass ist doch eine Aufgabe für den StateManager. Da ich jedoch keine Ahnung von jQuery und Asynchronem Events habe ist das Ganze für mich ein wenig schwierig nachzuvollziehen, aber folgendes habe ich versucht. Das erste JavaScript welches den Wert berechnet sieht wie folgt aus:

 $(".buybox--button").click(_function_ () { editor.saveProduct() _//If the product has been successfully saved._ .then(_function_ (result) { _//Saving the product state info._ stateId = result.stateId; returnToEditUrl = result.returnToEditUrl; $.publish('plugin/customerCanvas/onBeforeAddArticle', [stateId]); }) _//If there was an error thrown when saving the product._ .catch(_function_ (error) { saveData = handleError(error, "Save failed with exception: "); }); });

Ich feure also einen Event der die StateId weitergibt. Nun zum listener: Hier habe ich die jquery.add-article.js wie folgt angepasst:

 $.overridePlugin('swAddArticle', { _/\*\*_ _\* Gets called when the element was triggered by the given event name._ _\* Serializes the plugin element { __@link_ _$el} and sends it to the given url._ _\* When the ajax request was successful, the {__ @link_ _initModalSlider} will be called._ _\*_ _\*_ _@public_ _\*_ _@event_ _sendSerializedForm_ _\*_ _@param_ _{jQuery.Event} event_ _\*/_ sendSerializedForm: _function_ (event) { event.preventDefault(); _var_ me = _this_, opts = me.opts, $el = me.$el, ajaxData = $el.serialize(); ajaxData += '&isXHR=1'; $.subscribe('plugin/customerCanvas/onBeforeAddArticle', _function_(event, stateId) { ajaxData += '&customerCanvasState='; ajaxData += stateId; _console_.log(ajaxData); }); _console_.log(ajaxData); _if_ (opts.showModal) { $.loadingIndicator.open({ 'openOverlay': _true_ }); } $.publish('plugin/swAddArticle/onBeforeAddArticle', [me, ajaxData]); $.ajax({ data: ajaxData, dataType: 'html', method: 'POST', url: opts.addArticleUrl, success: _function_ (result) { $.publish('plugin/swAddArticle/onAddArticle', [me, result]); _if_ (!opts.showModal) { _return_; } $.loadingIndicator.close(_function_ () { $.modal.open(result, { width: 750, sizing: 'content', onClose: me.onCloseModal.bind(me) }); picturefill(); StateManager.updatePlugin(opts.productSliderSelector, 'swProductSlider'); $.publish('plugin/swAddArticle/onAddArticleOpenModal', [me, result]); }); } }); }, }); 

Zusemmgefasst habe ich folgenden Ablauf:

  1. JavaScript berechnet Werte sobald auf ein Button geklickt wurde.
  2. Dieser Wert wird mithilfe eines Events an das add cart plugin weitergereicht.
  3. Das add cart plugin fügt den berechneten Wert zu den AjaxDaten hinzu.
  4. Im Checkout Controller wird der Post Wert ausgelesen.

Nun habe ich das Problem mit dem Timming. Die Events werden zu verschiedenen Zeitpunkte ausgeführt was bedeutet das mir die Console folgendes ausgibt:

Wo liegt mein Denkfehler? Wie kann ich warten ob dieser Event auch tatsächlich ausgeführt wird?

Bitte habt ein wenig Verständnis dafür dass ich keine Ahnung von diesem jQuery gedöns habe. Ich bin über jeden Tipp dankbar.

Gruss

Alexander

Temporär habe ich eine Lösung gefunden welche Funktioniert - nur wieso weiss ich nicht ; )

 $.overridePlugin('swAddArticle', { /\*\* \* Gets called when the element was triggered by the given event name. \* Serializes the plugin element {@link $el} and sends it to the given url. \* When the ajax request was successful, the {@link initModalSlider} will be called. \* \* @public \* @event sendSerializedForm \* @param {jQuery.Event} event \*/ sendSerializedForm: function (event) { event.preventDefault(); var me = this, opts = me.opts, $el = me.$el, ajaxData = $el.serialize(); ajaxData += '&isXHR=1'; $.publish('plugin/customerCanvas/onBeforeAddArticle', ['']); $.subscribe('plugin/customerCanvas/onBeforeAddArticle', function(event, stateId) { ajaxData += '&customerCanvasState='; ajaxData += stateId; if (opts.showModal) { $.loadingIndicator.open({ 'openOverlay': true }); } $.publish('plugin/swAddArticle/onBeforeAddArticle', [me, ajaxData]); $.ajax({ data: ajaxData, dataType: 'html', method: 'POST', url: opts.addArticleUrl, success: function (result) { $.publish('plugin/swAddArticle/onAddArticle', [me, result]); if (!opts.showModal) { return; } $.loadingIndicator.close(function () { $.modal.open(result, { width: 750, sizing: 'content', onClose: me.onCloseModal.bind(me) }); picturefill(); StateManager.updatePlugin(opts.productSliderSelector, 'swProductSlider'); $.publish('plugin/swAddArticle/onAddArticleOpenModal', [me, result]); }); } }); }); }, }); 

Ich habe einfach alle Aktionen in mein Event gepackt und feuere den Event mit einem leeren Wert innerhalb des selben skriptes. Die Idee dahinter ist das mein Editor Script (welches nur eingebunden wird wenn ein Artikel auch einen entsprechenden Editor besitzt) den Wert im zuerst überreicht bevor ich mit dem leer wert komme. ABER ich habe mich hier glaub ich eher verrannt und ich weiss auch nicht wirklich wieso das funktioniert? Eigentlich müsste der Wert meiner Meinung nach mit der Implementation oben immer leer bleiben? Tut er aber nicht - Hab ich nur Glück oder kann man das so lassen?