Benutzer abhängige Ansichten oder Aktionen sind in der Shopware 6 Administration sehr selten. Aber gerade auf dem Dashboard kann toll Ansichten und Nachrichten unterbringen, die speziell für einen Benutzer oder eine Benutzergruppe gedacht sind. Aber dafür muss man wissen wer gerade eingeloggt ist, um z.B. ein Criteria mit den richtigen Filtern zu versehen.
Daten per Criteria abfragen und in einer Table oder einer Form darzustellen oder verarbeiten ist in der Shopware 6 Administration extrem einfach und fast zu 100% genau so wie in PHP. Aber manchmal will man auch auf eine sehr spezielle Art oder Weise Daten erhalten und diese dem Benutzer direkt als Download anbieten können.
Hier ein kleines Beispiel eines CSV-Downloads der von einem API-Controller mit der Route "/api/example-module/download/csv/{id}" kommt. Man kann aber genau so gut alles per Criteria abfragen und das CSV in JavaScript bauen.
Die Methode für den Download sieht mit Controller-Lösung so aus:
Das Prinzip ist an sich sehr einfach. Man baut sich ein a-Element mit gesetzten download-Attribute und simuliert einen Click darauf. Nur hinterlegt man hier die Daten als Data-URL und nicht die URL zum Controller direkt. Das würde nicht funktionieren als dann dort die Authorization-Infos im GET-Header fehlen würden.
Die Data-URL kann eben aus Daten von einem Controller gebaut werden oder direkt aus Daten, die JavaScript aggregiert wurden.
Sehr viel einfacher als die alten Lösungen mit FileSaver-Lib und viel hin und her wandeln von Blobs.
Während ja jede Entity eine id hat, hat nicht jede ein name-Field. Ich musste doch etwas suchen bis ich erstmal die Dokumentation zu der Component gefunden habe und dann mir klar war wie ich ein andere Feld angeben kann. Am Ende natürlich genau so wie man es sich dachte nur der Prop-Name ist irgendwie seltsam, weil Label ja auch anders dort verwendet wird als Begriff.
Das direkte Einbinden als Base64 Data-URL ist echt praktisch, aber man will ja nicht, dass die Benutzer nun endlos riesige Bilder darüber einbinden. Deswegen ist es eine gute Idee, die Bilder beim Einfügen auch gleich zu verkleinern. Das ist zum Glück mit dem Canvas-Element sehr einfach.
Die Callback-Function:
let onImageUploadFunc = function (elementId) {
return function(image) {
resizeImage(image[0], elementId);
}
};
function resizeImage(file, elementId) {
let image = new Image();
let url = window.URL ? window.URL : window.webkitURL;
image.src = url.createObjectURL(file);
image.onload = function (e) {
let canvas = document.createElement("canvas");
let ctx = canvas.getContext("2d");
let width = 600;
let factor = image.width / width;
let height = image.height / factor;
Eine Admin-UI lebt nicht nur von Tables sondern auch von sehr vielen Forms. Die möchte man ja nur ungern komplett per Hand bauen sondern etwas wie JSON-Schema benutzen, da man das auch auf Server-Seite für die Validierung nutzen kann.
Schon als ich mit React arbeiten musste, war ich sehr von den vorgefertigten Admin-Templates angetan. Jetzt darf ich auch mal damit rumspielen und meine ersten Erfahrungen damit sind schon relativ positiv. Da ich mit meinem Job synchron bleiben wollte habe ich mit CoreUI angefangen.
Die Installation über GitHub ist einfach und schnell.
Um ein eigens View anzulegen muss man an sich drei Dinge tun.
1. Die View anlegen:
2. In router/index.js die Component importieren und in die Router-Config einfügen:
3. In containers/_nav.js einen Link für die Sidebar einfügen:
Durch die Transition-Tag wird das Element eingeschlossen, dessen Änderung mit der Animation verknüpft werden soll. Der Name ist der der erste Teil des Animationsnamens.
.dialogbox-enter-active {
animation: open 0.8s;
}
.dialogbox-leave-active {
animation: open 0.4s reverse;
}
AngularJS hat beim IE (älter als Edge) ein Problem mit ng-change, wenn ein Input über eine DataList gefüllt wird. Dann wird einfach kein Event ausgelöst. Mit einer kleinen Hilf-Function und $scope.$applyAsync() in der Scope-Function kann man das aber reimplementieren.
function onChangeIE(value){
var ua = window.navigator.userAgent;
if((ua.indexOf('Trident/') > 0 || ua.indexOf('MSIE ') > 0) && ua.indexOf('Edge/') <= 0) {
angular.element(document.getElementById('my-ng-controller-element')).scope().myInputModel = value;
angular.element(document.getElementById('my-ng-controller-element')).scope().myNgChangeFunction();
Die beste Lösung wäre solche alten Browser nicht mehr zu supporten und dann vielleicht auch auf Vue.js oder eine aktuelle Angular-Version zu wechseln.
Aber für schnelles Prototypen, wo man wenig Code schreiben will, ist AngularJS noch immer sehr gut. Teilweise ist man so schnell damit, dass man während einer Diskussion die Ideen direkt nebenbei umsetzen und ausprobieren kann. Wenn man erst einmal viele Components schreiben muss, geht es nicht so gut, wie mit den AngularJS Templates und Dingen wie ng-options. Mit Vue.js ist man mit etwas Übung aber auch ähnlich schnell.
Wenn man sich generische Componenten in React oder Vue bastelt, wie Lists oder Grids/Tables kommt man schnell zu dem Punkt, wo man Werte aus einem Object extrahieren muss. Z. B. wenn man sich in einer Table eine Column definiert. Man könnte eine function rein reichen, die auf die konkrete Implementierung des Item zugeschnitten ist, aber oft will man nur die vorhandenen Werte im Object zur Anzeige bringen und nicht zu viel schreiben.
Wenn man einen Key hat und auf der ersten/obersten Ebene agiert wie bei item.id ist alles einfach. Bei item.sub.moreSub.verySub.id ist es schon schwieriger.. naja eigentlich nicht und jeder hat so etwas schon mal gebastelt. Hier meine Lösung die vielleicht jemanden 5 Minuten Arbeit ersparen kann :-)
function getObjectValue(obj, path){
let curObj = obj;
const parts = path.split(".");
for(let i = 0; i < parts.length; i++){
if(curOjb[parts] !== undefinded){
curObj = curObj[parts];
}
else {
return undefined;
}
}
return curObj;
}
Ich hatte in den letzten Tagen etwas mehr mit verschiedenen Formular-Generatoren in verschiedenen JS-Frameworks zu tun. Vorraussetzung bei allen was, dass die JSON-Schema als Schema-Sprache unterstützten. Bis jetzt war keiner dabei der wirklich fehlerlos funktionierte. Ich kann jetzt nicht sagen, ob es nicht doch irgendwie an mir lag, aber falls jemand bestätigen kann, das ein Problem kein generelles Problem dabei ist, wäre ich doch sehr glücklich und würde mich noch mal genauer damit beschäftigen.
Vue: FormSchema Native: lief erstmal ganz gut, aber wenn sich das Schema oder das Model im State geändert hat, würde die Form nicht neu gerendert. Wenn man eine Form-Component schreibt in die verschiedene Schemas rein gericht werden können zur Laufzeit ist das echt doof. Ansonsten machte es nämlich einen guten Eindruck.
React: react-jsonschema-form: bis jetzt das Beste nur gibt es leichte Probleme wenn man $schema mit etwas anderen als dem default-Schema rein reicht. Aber ansonsten funktioniert bis jetzt am Besten. Auch mit 3 Forms auf der Seite.
AngularJS Angular Schema Form: Wenn man nur eine Form auf der Seite braucht funktioniert es perfekt. Wenn ich aber zwei Forms mit zwei unterschiedlichen Schemas verwende, wollte die zweite Form nicht mehr rendern. Aber eine Form allein funktionierte echt super. Leider ist AngularJS aber ja nicht mehr wirklich supported und ich hätte lieber etwas für Vue gehabt, was genau so gut funktioniert.. eben dann auch mit 2-3 Form pro Seite. Edit: Problem hat sich in Luft aufgeloest...
Meine Suche geht weiter, weil ich Vue doch lieber mag als React. Oder am Ende doch selber schreiben oder ein andere auf JSON-Schema anpassen?
Bei Vue.js werden bei den Props, die an eine Unterkomponente übergeben werden, diese als Referenz übergeben. Wenn ich in der Unterkomponente etwas Ändere, werden diese Änderungen im selben Object durchgeführt, dass sich auch in der Oberkomponente befindet und ich kann diese Änderungen direkt dort verwenden. Ein Watcher sollte auch Änderungen erkennen können.
Bei React müßte ich eine callback-funktion mit in die Unterkomponente reinreichen und bei der Änderung diese antriggern, damit die Oberkomponente die geänderten Daten in denen eigenen State wieder übernehmen kann. Also wird in dem Sinne jede Reference, wie sie in Vue.js existiert hätte, durch eine selbst zu implementierende callback-Funktion ersetzt?
Macht das Sinn? Erzeugt es nicht nur mehr Arbeit und Code? Wo genau ist da der Vorteil? Oder habe ich da was falsch verstanden bei React?
Irgendwie werde ich mit React nicht wirklich warm. Es sind so Kleinigkeiten, die mich da stören oder mir das Gefühl geben, einiges wäre unnötig kompliziert in React.
Irgendwie scheint das v-for von Vue.js Probleme zu haben, wenn ein Array z.B. von 5-10 geht und nicht von 0-5. Ich musste jeden Falls erst einmal einen Offset berechnen, um im Array wieder alles von 0 beginnen zu lassen. Dann funktionierte wieder alles.
Blog-entries by search-pattern/Tags:
Möchtest Du AdSense-Werbung erlauben und mir damit helfen die laufenden Kosten des Blogs tragen zu können?