Über Postmessage API aus SubWindow auf das übergeordnete Fenster zugreifen

Hallo!

Ich schreibe ein Lightweight Backend Module und das funktioniert sehr gut. Ich zeige eine Liste mit Elementen, die per Klick auf ein entsprechendes Icon in einem Popup-Fenster bearbeitet werden können.

Das Popup-Fenster öffne ich als SubWindow mit Hilfe der postMessageApi:

var values = {
    width: 750,
    height: 360,
    component: 'customSubWindow',
    url: 'MyModule/edit',
    title: 'Bearbeiten'
};

postMessageApi.createSubWindow(values);

 

Ich übermittle auch erfolgreich Daten wie folgt:

window.setTimeout(function() {
    postMessageApi.sendMessageToSubWindow({
        component: values.component,
        params: {
            id: id
        }
    });
}, 1000);

 

Im Template (edit.tpl) des SubWindows greife ich folgendermaßen auf die Nachricht des übergeordneten Fensters zu:

var subscriber = window.events.subscribe('get-post-message', function (eOpts) {
    subscriber.remove();
    if (eOpts.result) {
        id = eOpts.result.id;
    }
});

 

Soweit, so gut. 

Aber wie kann ich eine Nachricht über die Postmessage API von einem SubWindow zum überordneten Fenster übermitteln?

Ich möchte die Liste darüber informieren, dass sich gerade ein Eintrag geändert hat und sie neu geladen werden muss.

Danke im Voraus!

Ja das Thema gab es hier auch schon unbeantwortet: https://forum.shopware.com/discussion/37387/postmessage-api-kommunikation-zwischen-den-fenstern-iframes/p1

Hab mich damit noch nicht beschäftigen müssen, steht demnächst an. Sowas wie sendMessageToParentWindow o.ä. gibt es nicht? Sonst könntest du gucken wie das sendMessageToSubWindow aufgebaut ist und das dann entweder replizieren oder reversen.

1 „Gefällt mir“

@BestShopPossible schrieb:

Ja das Thema gab es hier auch schon unbeantwortet: https://forum.shopware.com/discussion/37387/postmessage-api-kommunikation-zwischen-den-fenstern-iframes/p1

Hab mich damit noch nicht beschäftigen müssen, steht demnächst an. Sowas wie sendMessageToParentWindow o.ä. gibt es nicht? Sonst könntest du gucken wie das sendMessageToSubWindow aufgebaut ist und das dann entweder replizieren oder reversen.

Vielen Dank für deine Antwort. Leider gibt es keine sendMessageToParentWindow Funktion, obwohl diese Funktionalität sogar im PostMessage Working Draft vorgesehen ist: 

HTML 5 (7.2.1)

So wie es aussieht, werde ich wohl selbst etwas implementieren müssen, so wie du es vorgeschlagen hast.

Sehr schade und für mich nur bedingt nachvollziehbar.

Naja oder du verzichtest auf subWindow und machst ein normales modal in dem du dir die Daten als json über ajax hin un her schickst.

Also ich schick momentan per custom events Infos hin und her - Bsp. mainWindow:

//...

window.parent.document.addEventListener('customer_communication/message/load', function(event){
	postMessageApi.sendMessageToSubWindow({
		component: 'messageWindow',
		params: {
			source: 'parent',
			data: {
				uuid: postMessageApi.getInstance(),
				name: postMessageApi.getComponentName()
			}
		}
	});
}, false);

window.parent.document.addEventListener('customer_communication/message/delete', function(event){
	var data = event.detail;
	//...
}, false);

postMessageApi.createSubWindow({
	width: 900,
	height: 650,
	component: 'messageWindow',
	url: '/backend/costumer_communication/message?id=' + me.id,
	title: me.subject
});

 

Und Bsp. im subWindow:

var mySubWindowPlugin = function(messageId){
	this.id = messageId;
	this.parentWindow = null;
	
	//...
	this.delete = function(){
		var me = this;
		//..
		var event = new CustomEvent('customer_communication/message/delete', { detail: data });
		window.parent.document.dispatchEvent(event);	
	}
	//...
}

var initSubscription = window.events.subscribe('initialized-api', function(obj) {
	initSubscription.remove();

	var event = new CustomEvent('customer_communication/message/load');
	window.parent.document.dispatchEvent(event);

	//...
});

var postMessageSubscription = window.events.subscribe('get-post-message', function (obj) {
	if(obj.result.source && obj.result.source == 'parent'){
		mySubWindowPlugin.parentWindow = obj.result.data;
		//...
	}
});

 

Vielleicht hilft’s ja wem irgendwie weiter.

2 „Gefällt mir“

Du kannst mit component:main ganz einfach Nachrichten an das Hauptfenster schicken.

postMessageApi.sendMessageToSubWindow({
  component: 'main',
  params: {
    msg: 'Diese Nachricht geht an das übergeordnete Fenster'
  }
});

Viele Grüße

Stimmt, sendMessageToSubWindow kann man auch an das “Elternfenster” addressieren - in manchen Szenarios also sicher der bevorzugte Weg. In meinem Fall war das suboptimal, da ich meine EventListener teils nicht nur in einem Fenster sitzen hab und es dann schlussendlich konsistener fand, alles über konkrete Events zu lösen.

Noch ergänzend zum Thema, weshalb ich eigentlich auf den Thread hier stoß: ich war auf der Suche nach einer Möglichkeit für das Elternfenster (oder irgendein “interessiertes” anderes Fenster) das Schließen des Unterfensters zu registrieren. Das postMessageApi-Event 'component/destroy  feuert leider nicht, wenn der Benutzer auf die x-Schaltfläche des Fensterrahmens klickt. Falls noch wer genau daran hängen bleibt, hier meine momentane (Zwischen-?)Lösung:

var module = parent.window.Shopware.ModuleManager.modules.get(postMessageApi.getInstance());
var windowApp = module.windows.get('nameDesSchließendenFensters');

windowApp.on('beforeclose', meinBeforeCloseHandler, this);
// Oder:
windowApp.on('close', meinCloseHandler, this);

 

Wenn man vom Modul aus irgendwie eleganter an die Enlight-SubApp kommt, gerne einklinken :slight_smile:

1 „Gefällt mir“