Backend/Artikeldetails - ErwAttribute nicht lese-/schreibbar

Hallo Zusammen, analog zu dem Developers Guide Beispiel habe ich die Backendmaske Artikel-Details um einen Tab erweitert um dort zwei erweiterte Attribute zu verwalten. Die Datenbank wurde erfolgreich beim installieren des Plugins wie folgt erfoglreich erweitert: $shopware\_obj-\>Application()-\>Models()-\>addAttribute('s\_articles\_attributes', 'ezi', 'issos\_art\_nr','varchar(24)',true,null); $shopware\_obj-\>Application()-\>Models()-\>addAttribute('s\_articles\_attributes', 'ezi', 'stock\_names','varchar(255)',true,null); Shopware()-\>Models()-\>generateAttributeModels(array('s\_articles\_attributes')); Die Webmaske wurde ebenfalls erfolgreich erweitert (inkl. Snippsets), ich sehe den neuen Tab und die zwei neuen Felder, diese wurde wie folgt definiert: me.eziIssosArtNr = Ext.create('Ext.form.field.Text', { name:'attribute[eziIssosArtNr]', fieldLabel:'{s name=ezi\_detail/issos\_art\_nr}ISSOS-article-no{/s}', allowBlank: true,anchor:'95%',labelWidth:150,minWidth:250 }); me.eziStockNames = Ext.create('Ext.form.field.Text', { name:'attribute[eziStockNames]', fieldLabel:'{s name=ezi\_detail/stock\_names}ISSOS-stock-name{/s}', allowBlank: true,anchor:'95%',labelWidth:100,minWidth:250 }); „Shopware.apps.Article.model.Attribute“ wurde erweitert. Das die Zeilen an der richtigen Stelle landen, kann ich z.B. mit Firebug Debugger feststellen Ext.define('Shopware.apps.Article.model.Attribute', { extend: 'Ext.data.Model', fields: [{ name:'eziIssosArtNr', type:'string' }, { name:'eziStockNames', type:'string' }, { name: 'id', type: 'int' }, { name: 'articleId', type: 'int', useNull : true }, ... Ich sehe auch in „\templates_default\backend\article\model\article.js“, das die erwartete Assoziation vorhanden ist: { type: 'hasMany', model: 'Shopware.apps.Article.model.Attribute', name: 'getAttribute', associationKey: 'attribute' }, In den Feldern geschriebene Inhalte werden beim Speichern aber nicht in die DB gespeichert, bzw. in die DB manuell eingetragene auch nicht dort angezeigt. Sie werden also nicht „automatisch befüllt“. Stehen die erweiterten Artikel-Attribute hier nicht zur Verfügung? Oder habe ich irgendwo was überlesen/missverstanden? Vielen Dank im voraus.

Wenn das das ist was ich meine, dann müssen die Freifelder auch die richtigen Namen attr1 attr2 usw… haben

Jein, attr1 attr2 usw. sind auch Teil von “Shopware.apps.Article.model.Attribute” und sie stehen in der Datenbank in der selben Tabelle (s_articles_attributes). Die genannten Tabelle wurde (wie im erstem Codeabschnitt gezeigt) erweitert durch 2 weitere Attribute. Mittels folgendem Code //{block name="backend/article/model/attribute/fields" append} { name:'eziIssosArtNr', type:'string' }, { name:'eziStockNames', type:'string' }, //{/block} wird aber die Field-Definition aus “\templates_default\backend\article\model\attribute.js” erweitert, so dass im Webbrowser folgendes zu sehen ist (4+5 Zeile): Ext.define('Shopware.apps.Article.model.Attribute', { extend: 'Ext.data.Model', fields: [{ name:'eziIssosArtNr', type:'string' }, { name:'eziStockNames', type:'string' }, { name: 'id', type: 'int' }, { name: 'articleId', type: 'int', useNull : true }, { name: 'articleDetailId', type: 'int', useNull : true }, { name: 'attr1', type: 'string' }, ... { name: 'attr20', type: 'string' }] }); Laut dem Wiki Beitrag hätte ich daher erwartet, dass die Felder nun “automatisch befüllt” würden, Zitat: “Dieses Vorgehen ist bei Formularen unbedingt empfehlenswert, da nur so das automatische Setzen und Lesen von Models durch ExtJS genutzt werden kann.” Aber auch wenn ich attr1 oder attr2 statt der neuen Tabellen-Spalten-Namen eingeben - laden und speichern der Werte aus/in die DB funktioniert hier trotzdem nicht. Daher der verdacht, dass diese Attribute hier gar nicht geladen und somit nicht beachtet werden. Die Assoziation ist zwar da, ich finde aber nirgends, dass sie tatsächlich aufgerufen würde. Wie kann ich also auf die Attribute zugreifen (lesend/schreibend)?

Ok, bin nun ein Stück weiter. Habe mich durchgesucht im Code bis “\templates_default\backend\article\controller\main.js”. Dort finde ich folgenden Code: openExistingArticle: function(id) { var me = this; // Create main window me.openMainWindow(); //the batch store is responsible to load all required stores for the detail page in one request me.batchStore = me.getStore('Batch'); me.batchStore.getProxy().extraParams.articleId = id; me.batchStore.load({ callback: function(records, operation) { var storeData = records[0]; me.subApplication.fireEvent('batchStoreLoaded', storeData, operation, true); } }); }, Wenn ich an Zeile 14 stoppe und storeData.raw.article[0].attribute[‘eziIssosArtNr’] abfrage, so sehe ich den Inhalt der in der Datenbank steht. Geladen werden die Werte also… Feld mir nur noch der Grund wieso der nun sichtlich geladene Wert nicht im Feld angezeigt (und auch gespeichert) wird. Kann mir jemand weiterhelfen? Ist die Art und weiße ich ich “name” definiert habe falsch? Liegt das Problem daran, dass das Feld in einem Neuen Tab angezeigt wird und nicht direkt im Reiter “Stammdaten”?

Leider hatte ich immer noch kein erfolgt. Hat jemand irgend ein Vorschlag machen wie ich die Datenbank-Werte in die Felder lade und die Änderung in die Datenbank speichern kann? Auch Links zu ähnlichen Themen würde weiterhelfen, denn noch bin ich am Anfang meiner Einarbeitung in der Shopware Programmierung… Aber irgendwie wie fehlt mir hier der konzeptionelle Hintergrund von ExtJS um zu wissen wo ich nun weiter suchen kann. Vielen Dank im voraus.

Hallo ich habe dein Posting gesehen und wollte mal fragen ob du schon eine Lösung gefunden hast? Ich stehe nämlich vor dem selben Problem und denke das hier mehr im Argen ist.

Hallo Almare, nein, stehe leider immer noch an der selben Stelle. Wie mir scheint wurde das laden/setzen/auslesen der Erweiterten Attribute in Artikel-Details vergessen. Wenn man weiß wo, dann ist dies vermutlich ein Einzeiler… Leider weiß ich inzwischen nicht mehr wo ich noch suchen könnte. Bin aber für jeden Hinweis offen.

Haha in der Tat ich habe es gerade herausgefunden. MIch hat dieser Scheiß echt den letzten Nerv geraubt!!! Also ich will mal versuchen es zu erklären. 1 Schritt : Die Daten aus den Attributen auslesen (Bei mir sind diese in einem weiteren Tab untergebracht) createMeinTab: function(article, stores, eOpts) { var me = this, tab = eOpts.tab; tab.add(me.createMeineComponents()); // Variablen zuweisen me.MEIN\_FELD1.setValue(article.getAttributeStore.data.items[0].data.MEIN\_ATTRIBUT\_FELD\_1); me.MEIN\_FELD2.setValue(article.getAttributeStore.data.items[0].data.MEIN\_ATTRIBUT\_FELD\_2); tab.setDisabled(article.get('id') === null); }, Das gleiche muss in die Funktion wenn das Tab einen neuen Artikel lädt articleChange: function(article, tabConfig) { var me = this; // Variablen zuweisen me.MEIN\_FELD\_1.setValue(article.getAttributeStore.data.items[0].data.MEIN\_ATTRIBUT\_FELD\_1); me.MEIN\_FELD\_2.setValue(article.getAttributeStore.data.items[0].data.MEIN\_ATTRIBUT\_FELD\_2); }, Nun werden die Felder angezeigt und befüllt!!! Weiter im Context. Das Speichern der neuen Werte. Es muss ein event in deinem Controller erzeugt werden das auf den Namen saveArticle reagiert. Dieser Event ist im Main Window der Artikel definiert. Hier fügen wir wieder unsere Werte dem Store hinzu. onSaveArticle:function(win, article, options){ var me = this, mainController = me.getController('Main'), mainWindow = mainController.mainWindow; article = mainWindow.article; article.getAttributeStore.data.items[0].data.MEIN\_ATTRIBUTE\_FELD\_1 = Ext.getCmp('MEIN\_FELD\_1').getValue(); article.getAttributeStore.data.items[0].data.MEIN\_ATTRIBUTE\_FELD\_2 = Ext.getCmp('MEIN\_FELD\_2').getValue(); } Das war es auch schon. Hier ist allerdings keine Validierung eingebaut. Es gibt sicher noich eine bessere Lösung aber es funktioniert zumindest. Eine Woche und sämtliche Tutorials haben mich nicht weitergebracht. Bin offen für Verbesserungen. Dies soll zumindest der Anfang sein. Feedback willkommen

1 „Gefällt mir“

Hm, wie mir scheint hast du genau das gemacht wovon im Developer Guide beschrieben wird, dass man sich das sparen kann: [quote]…Durch die Namensgebung, die sich am jeweiligen ExtJS-Model orientiert, können wir uns die Logik zum Laden und Speichern des Inhalts der Eingabefelder komplett sparen: ExtJS besorgt dies automatisch… Um unsere Eingabefelder automatisch befüllen zu lassen, können wir einfach die gewünschten Feldnamen des Models als Name des Eingabefeldes nutzen… Dieses Vorgehen ist bei Formularen unbedingt empfehlenswert, da nur so das automatische Setzen und Lesen von Models durch ExtJS genutzt werden kann. [/quote] Die angesprochene Namensgebung ist „attribute[MEIN_FELD]“. Das hab ich auch so gemacht. Wie mir scheint sind aber die Erweiterten Attribute der Artikel nichts als „stores“ abgebildet, vermutlich daher auch nicht automatisch gesetzt/gespeichert. Zu allen anderen Werten finde ich dazu eine „bindStore()“ Anweisung. Sofern diese Anweisung (und der anderen dazugehörigen) vergessen wurden, dann ist es ein Bug. Sofern sie bewusst nicht gemacht wurden, dann ist es zumindest ein Konzeptbruch - wenn man weiß, dass dieses Konzept nur für den einen oder anderen Bereich gilt, dann würde man sich ja nicht wundern, dass man es dort „zu Fuß“ machen muss. Aufgrund das es im Wiki hieß, man kann sich die eigene Logik sparen hatte ich bisher noch keinen eigenen Controller implementiert. Dieser ist aber Voraussetzung für deine beschrieben Logik. Kann jemand sagen ob dieses Konzept nur für die Kundendetails gilt und es für die Artikel bewusst nicht?

Richtig, das habe ich aucbh gelesen. Leider hat dies aber hier anscheinend noch niemand geschafft es so umzusetzen. Bei mir und wie bei allen anderen hat es anscheinend nicht funktioniert. Daher lieber eine „schlechte“ Lösung die läuft, als eine die gar nicht funktioniert bzw. wir nicht wissen wie sie korrekt angewendet wird. Ich persönlich würde auch die genannte Lösung bevorzugen, allerdings geht sie nicht. Bug? Das kann ich leider nicht bestätigen, daher müsste man erstmal wissen was wir falsch gemacht haben.

So ich habs herausgefunden. Das hat mich echt jetzt genervt. Die Lösung um Store Variablen den Feldern zuzuweisen läuft über .loadRecord( ) Funktion. Doku: http://docs.sencha.com/extjs/4.0.7/#!/a … oadRecords Ein kleines Beispiel hier noch: onTabActivated: function(window) { var me = this; window.MEINStore.load({ callback: function(records, operation) { if (!operation.wasSuccessful()) { return; } if (records.length \> 0) { me.record = records[0]; me.getMEIN\_REF\_MIT\_FORMULAR().loadRecord(me.record); } else { // Create a new, empty record me.record = Ext.create('Shopware.apps.Article.model.MEIN.MODEL'); // Do not pass empty record here: This way the components' default values will be used me.getMEIN\_REF\_MIT\_FORMULAR().loadRecord(); } } }); }, Ich hoffe das hilft weiter

Hallo Ich sehe, dass dieser Beitrag ein Bisschen älter ist. Jedoch möchte ich gerne ein Plugin auf Version 5.0.2 erstellen, welches meine ErwAttribute in einem selbstständigen Tab bei Artikeldetails im Backend anzeigt. Ich habe noch nicht viel Erfahrung und kann diesem Beitrag nicht ganz folgen, da nicht gesagt wird welches File gerade angesprochen wird. Ist es möglich, wenn beschrieben wird welche Events man subscriben muss und welche Views erstellt/bearbeitet werden sollen? Vielen Dank

Hallo Ich bin nun schon viel weiter gekommen. Ich habe nun folgende Schritte gemacht: Bootstrap.php //Event subscriben $this-\>subscribeEvent( 'Enlight\_Controller\_Action\_PostDispatch\_Backend\_Article', 'onEnlightControllerActionPostDispatchBackendArticle' ); //Meine Views registrieren public function onEnlightControllerActionPostDispatchBackendArticle(Enlight\_Event\_EventArgs $arguments) { $arguments-\>getSubject()-\>View()-\>addTemplateDir( $this-\>Path() . 'Views/' ); //Hier lädst du alle Javascript Dateien die ein Override enthalten. if ($arguments-\>getRequest()-\>getActionName() === 'load') { $arguments-\>getSubject()-\>View()-\>extendsTemplate( 'backend/article/view/detail/my\_window.js' ); } //Hier erweiterst du die APP.JS um eigene Komponenten (Models, Views, Stores, Controllers) hinzuzufügen if ($arguments-\>getRequest()-\>getActionName() === 'index') { $arguments-\>getSubject()-\>View()-\>extendsTemplate( 'backend/article/my\_app.js' ); } } my_window.js //{block name="backend/article/view/detail/window" append} Ext.define('Shopware.apps.Article.view.detail.Window', { override:'Shopware.apps.Article.view.detail.Window', /\*\* \* Creates the main tab panel which displays the different tabs for the article sections. \* To extend the tab panel this function can be override. \* \* @return Ext.tab.Panel \*/ createMainTabPanel: function() { var me = this; var formTab = me.callParent(arguments); //Der Container für das Tab =\> Der Tab selber me.testTab = Ext.create('Ext.container.Container', { title: 'Test Tab', disabled: true, name: 'test-tab', layout: 'border' }); me.mainTab.insert(me.testTab); return formTab; }, //Der Inhalt des Tabs createTestContent: function() { var me = this; me.testContent = Ext.create('Shopware.apps.Article.view.test.Test', { height: '100%', width: '100%', autoScroll:true, margin: 10 }); return me.testContent; }, onStoresLoaded: function(article, stores) { var me = this; me.callParent(arguments); me.testTab.add(me.createKmudoContent()); me.testTab.setDisabled(false); }, }); //{/block} test.js //{namespace name=backend/article/view/main} //{block name="backend/article/view/test/test"} Ext.define('Shopware.apps.Article.view.test.Test', { /\*\* \* Define that the category drop zone is an extension of the Ext.panel.Panel \* @string \*/ extend:'Ext.form.FieldSet', /\*\* \* List of short aliases for class names. Most useful for defining xtypes for widgets. \* @string \*/ alias:'widget.article-test-test', /\*\* \* Set css class for this component \* @string \*/ cls: Ext.baseCSSPrefix + 'article-test-test', /\*\* \* Layout for the component \*/ layout: 'anchor', /\*\* \* Defaults for the panel items \* @object \*/ defaults: { anchor: '100%' }, /\*\* \* The initComponent template method is an important initialization step for a Component. \* It is intended to be implemented by each subclass of Ext.Component to provide any needed constructor logic. \* The initComponent method of the class being created is called first, \* with each initComponent method up the hierarchy to Ext.Component being called thereafter. \* This makes it easy to implement and, if needed, override the constructor logic of the Component at any step in the hierarchy. \* The initComponent method must contain a call to callParent in order to ensure that the parent class' initComponent method is also called. \* \* @return void \*/ initComponent:function () { var me = this; me.items = me.createContent(); me.callParent(arguments); }, /\*\* \* Creates the content \* @return Ext.container.Container \*/ createContent: function() { var me = this; return Ext.create('Ext.container.Container', { anchor: '100%', focusable: false, margin: 10, items: [{ xtype: 'checkbox', name: 'mein\_erstes\_feld', fieldLabel: 'Sehenswert', boxLabel: 'Ob Artikel sehenswert ist', inputValue: true, uncheckedValue:false }, { xtype: 'textfield', name: 'mein\_zweites\_feld', allowBlank: false, fieldLabel: 'Begründung', supportText: 'Warum denn?' }] }); } }); //{/block} Mit diesen Anpassungen hier hat man ein neues Tab und Inhalt. Nun jedoch meine Frage: Ich habe in der Datenbank die Felder ‘mein_erstes_feld’ und ‘mein_zweites_feld’ und möchte diese in meinem Tab auslesen und speichern können. Ich weiss, dass ich im File my_app.js die Views, Controller, Store und Model einbinden muss, aber diese Version hier funktioniert nicht… (Alle gefundenen Beispiele Shopware Version 4) //{block name="backend/article/application" append} //{include file="backend/article/controller/test.js"} //{include file="backend/article/model/test.js"} //{include file="backend/article/store/test.js"} //{include file="backend/article/view/test/test.js"} //{/block} Was ist der korrekte Weg im Shopware 5? Und wie muss der Controller, Model und Store aussehen, dass ich die Felder von s_articles_attributes auslesen kann? Vielen Dank

Hallo Ich bin wieder einen Schritt weiter gekommen, benötige aber immer noch Hilfe. Wenn ich im my_app.js wie oben die Files “einfüge” werden sie geladen, aber an der falschen Stelle. Wenn ich das original app.js nehme und dies gänzlich überschreibe und mein View, Store und Controller in die gegebenen Felder hinzufüge werden sie an den korrekten Stellen geladen. Das aber kann ja nicht der Weg sein, wenn man Plugins entwickelt… Beim Model habe ich nun attribute.js folgendermassen appended: //{block name="backend/article/model/attribute/fields" append} { name : 'mein\_erstes\_feld', type: 'boolean' }, { name : 'mein\_zweites\_feld', type: 'string' }, //{/block} Wie muss ich nun den Controller, View und Store einrichten damit mein Tab die Daten erhält?

Hallo kmudo, [quote=„kmudo“][…] Beim Model habe ich nun attribute.js folgendermassen appended: //{block name="backend/article/model/attribute/fields" append} { name : 'mein\_erstes\_feld', type: 'boolean' }, { name : 'mein\_zweites\_feld', type: 'string' }, //{/block} […][/quote] ohne den Code oben angesehen zu haben ( sorry aber den kann man so nicht lesen bitte benutze das „code“ Tag ) fällt mir gleich auf, dass du im Model die Felder falsch gemappt hast. Diese werden von Shopware in die „Camel“-Schreibweise umgewandelt. So wird der Article ExtJS App deine Werte nicht richtig zuordnen. So sollte das gehen: //{block name="backend/article/model/attribute/fields" append} { name : 'meinErstesFeld', type: 'boolean' }, { name : 'meinZweitesFeld', type: 'string' }, //{/block} Die ExtJS Anwendung erweiterst du mit „override“. Du musst aber nur die Dateien überschreiben, die du auch ändern willst ( nicht die gesamte ExtJS Anwendung ). Hier gibt es ein gutes Tutorial dazu. Viele Grüße edit: Ich sehe gerade, dass das Code Tag nicht funktioniert *facepalm* Dann könntest du den Code ja vielleicht hier mal reinstellen: http://gist.github.com