Digitale Unterschrift

Digitale Unterschrift als Control in SAPUI5

Ausgangssituation

In Zeiten der Digitalisierung und dem papierlosen Büro gehören digitale Unterschriften heutzutage zum modernen Unternehmensalltag. Verträge und Dokumente werden bereits an vielen Stellen nicht mehr auf Papier, sondern auf Tablets oder Handys unterzeichnet und direkt digital abgespeichert. So umgeht man unnötig analoge Papierarbeiten und man kann sich um die wichtigen Dinge im Alltag kümmern.

Wieso also nicht Verträge in modernen Fiori-Oberflächen unterzeichnen? SAP bietet standardmäßig diverse, schick aussehende UI5 Controls an, mit denen man Tabellen, Graphen oder Diagramme darstellen kann, also auch ein Control für digitale Unterschriften?
Derzeit leider nein. Also warum nicht selber ran und mit modernen HTML5 und JavaScript-Optionen ein eigenes Control bauen, das wir jedes mal einsetzen können, wenn wir eine digitale Signatur in unserer App benötigen.

(Wer sich das komplette Coding als Control kopieren möchte, kann auch gerne einfach an das Ende des Blogartikels springen und den Code kopieren.)

Das Ziel

Das Endergbnis soll in etwa wie im Folgenden aussehen. Wir möchten ein eigenständiges Control, mit folgenden Eigenschaften:

  • Attribute/Properties, die man in der XML setzen und verändern kann
  • Responsible, sowohl auf Desktop, als auch auf mobilen Endgeräten anwendbar
  • Signatur als Bild speichern können
  • Signaturbereich wieder löschen können

Eigene Control erstellen – der Grundbaustein, das Fundament

Wie man bestimmte Controls erweitert und auf bestehenden Controls aufbaut, wurde bereits in einem vorherigem Blog beschrieben.

In diesem Blog erstellen wir unser eigenes Control. Zunächst das Grundgerüst. Wir habe uns ein neues Projekt mittels “SAP UI5 Application”-Template erstellt, sodass das Grundgerüst vorhanden ist und wir eine leere App besitzen, in der wir die Digitale Signatur einfügen. In dieses Grundgerüst erweitern wir die Ordnerstruktur unter “webapp” um den Ordner “custom” und den Unterordner “controls”. Hier erstellen wir uns eine neue JavaScript-Datei, die den Namen unseres Controls hat, in meinem Fall “DigitalSignature.js”.

 

In dieses neue Control arbeiten wir nun das Coding ein, das letztlich unsere Signatur zeichnet und die Funktionalitäten bereitstellt.

Das Grundgerüst unseres individuellen Controls sieht wie folgt aus und ist letztendlich “einfach nur” eine Erweiterung eines allgemeinem SAPUI5 Controls. Wir erweitern das Control um unsere eigene Anpassungen, die in dem Ordner “custom/controls/” in der Datei “DigitalSignature” wiederfinden zu sind.

sap.ui.define(
	["sap/ui/core/Control"],
	function (Control) {
		return Control.extend("custom.controls.DigitalSignature", {
			metadata: {
				properties: {},
				aggregations: {}
			},
			renderer: function (oRm, oControl) {
				},
			onAfterRendering: function (oEvent) {
				//if I need to do any post render actions, it will happen here
				if (sap.ui.core.Control.prototype.onAfterRendering) {
					sap.ui.core.Control.prototype.onAfterRendering.apply(this, arguments); //run the super class's method first

				}
			}
		});
	});

Nun können wir unsere digitale Signatur bereits mit nur kleinen Anpassungen in unsere View einpflegen:

<mvc:View controllerName="de.acando.blog.DigitalSignatureBlog.controller.MainView" xmlns:html="http://www.w3.org/1999/xhtml"
	xmlns:mvc="sap.ui.core.mvc" displayBlock="true" xmlns="sap.m" xmlns:customControl="de.acando.blog.DigitalSignatureBlog.custom.controls">
	<App id="idAppControl">
		<pages>
			<Page title="{i18n>title}">
				<content>
					<customControl:DigitalSignature id="digitalSignatureId"/>
				</content>
			</Page>
		</pages>
	</App>
</mvc:View>

 

Wenn man die App nun startet erkennt man jedoch relativ schnell, dass der Inhalt noch sehr leer ist. Dies liegt natürlich daran, dass wir in der Methode “renderer” unseres eigenen Controls noch keine Inhalte zeichnen.

Aus dem Nichts entsteht eine Box – Die Wände hochziehen

Die digitale Signatur erstellen wir mit dem HTML5 Element Canvas. Mit Canvas lassen sich Boxen, Linien, Kreise und Rechtecke in den verschiedensten Formen und Farben zeichnen und ist daher sehr gut geeignet für unsere Anwendung.

Zudem müssen wir uns Gedanken darüber machen, welche Eigenschaften des Controls der User letztlich verändern können soll. Wie wäre es mit den folgenden Eigenschaften:

  • Höhe des Bereichs für die Unterschrift – width
  • Breite des Bereichs für die Unterschrift – height
  • Füllfarbe des Bereichs für die Unterschrift – fillColor
  • Farbe der Unterschrift – signatureColor
  • Breite der Linie der Unterschrift – lineWidth
  • Form der Linie der Unterschrift – lineCap
  • Farbe des Rahmen – borderColor
  • Breite des Rahmen – borderSize
  • Stil/Form des Rahmen – borderStyle

Diese Eigenschaften können wir zu den Properties der Metadaten hinzufügen. Das Hinzufügen der Attribute zu den Properties hat in erster Linie zwei positive Nebeneffekte.

  1. Durch das Hinzufügen dieser Attribute zu den Properties werden automatisch die get- und set-Methoden der jeweiligen Attribute erstellt, ohne dass wir die Methoden codieren müssen.
  2. In der XML-View können wir die Attribute direkt dem Control zuweisen, ohne dass wir Attribute im Controller setzen müssen
metadata: {
	properties: {
		width: {
			type: "sap.ui.core.CSSSize",
			defaultValue: "auto"
		},
		height: {
			type: "sap.ui.core.CSSSize",
			defaultValue: "auto"
		},
		borderColor: {
			type: "sap.ui.core.CSSColor",
			defaultValue: "#000000"
		},
		borderSize: {
			type: "sap.ui.core.CSSSize",
			defaultValue: "1px"
		},
		borderStyle: {
			type: "string",
			defaultValue: "none" //none, hidden, dotted, dashed, solid, double, groove, ridge, inset, outset, initial, inherit
		},
		fillColor: {
			type: "sap.ui.core.CSSColor",
			defaultValue: "#FFFFFF"
		},
		signatureColor: {
			type: "sap.ui.core.CSSColor",
			defaultValue: "#000000"
		},
		lineWidth: {
			type: "float",
			defaultValue: 1.5
		},
		lineCap: {
			type: "string",
			defaultValue: "round" //round, butt, square
		}
	},
	aggregations: {}
},

Nun zur renderer-Funktion. Hier “zeichnen” wir nun das Canvas-Element, also die Fläche, in der wir letztlich unsere Unterschrift zeichnen möchten.
In der dritten Zeile fügen wir die Attribute ein, die unser Control durch die xml-View mitbekommt, bspw. die ID des Controls.

renderer: function (oRm, oControl) {
	oRm.write("<canvas class='signature-pad' ");
	oRm.writeControlData(oControl);
	oRm.addStyle("width", oControl.getWidth());
	oRm.addStyle("height", oControl.getHeight());
	oRm.addStyle("border", oControl.getBorderSize() + " " + oControl.getBorderStyle() + " " + oControl.getBorderColor());
	oRm.writeStyles();
	oRm.write("/>");
},

Ein erstes Ergebnis? Wenn wir die App starten sehen wir leider noch nichts. Das bedeutet jedoch nicht, dass wir einen Fehler verursacht haben. Ein Blick mit den Browser Entwicklungstools zeigt, dass das Feld vorhanden ist.

Im Endeffekt haben wir unserem Bereich lediglich noch keine Farben gegeben. Dies machen wir nun in unserer onAfterRendering-Methode, da wir auf unser HTML5-Element zugreifen wollen, dass hierfür schon “gerendert” sein muss. Wir lagern die Methode aus, um diese wieder benutzbar machen zu können und um unseren Code sauber zu halten.

onAfterRendering: function (oEvent) {
	//if I need to do any post render actions, it will happen here
	if (sap.ui.core.Control.prototype.onAfterRendering) {
		sap.ui.core.Control.prototype.onAfterRendering.apply(this, arguments); //run the super class's method first
		this._drawSignatureArea(this);
	}
},

_drawSignatureArea: function (oControl) {
	var canvas = $("#" + oControl.getId())[0]; //This get´s our canvas-element by jQuery
	var context = canvas.getContext("2d"); //Getitng the context of our canvas-area
        canvas.width = canvas.clientWidth;
        canvas.height = canvas.clientHeight;
	context.fillStyle = oControl.getFillColor(); //Setting the FillColor/FillStyle
	context.strokeStyle = oControl.getSignatureColor(); //Setting the SignaturColor/StrokeStyle
	context.lineWidth = oControl.getLineWidth(); //Setting the SignatureLineWidth
	context.lineCap = oControl.getLineCap(); //Setting the LineCap of the Signature
	context.fillRect(0, 0, canvas.width, canvas.height);
},

 

Siehe da, wir haben ein erstes Ergebnis. Wir sehen nun unsere Fläche und können diese mit verschiedensten Attributen in der XML-View Einstellungen ändern. Im Folgenden zwei Beispiele:

  • Standard
    <mvc:View controllerName="de.acando.blog.DigitalSignatureBlog.controller.MainView" xmlns:html="http://www.w3.org/1999/xhtml"
    	xmlns:mvc="sap.ui.core.mvc" displayBlock="true" xmlns="sap.m" xmlns:customControl="de.acando.blog.DigitalSignatureBlog.custom.controls">
    	<App id="idAppControl">
    		<pages>
    			<Page title="{i18n>title}">
    				<content>
    					<customControl:DigitalSignature id="digitalSignatureId"/>
    				</content>
    			</Page>
    		</pages>
    	</App>
    </mvc:View>
    

  • Orange Hintergrundfläche, dicker lilaner gepunkteter Rahmen und Weite auf 7 0%
    <mvc:View controllerName="de.acando.blog.DigitalSignatureBlog.controller.MainView" xmlns:html="http://www.w3.org/1999/xhtml"
    	xmlns:mvc="sap.ui.core.mvc" displayBlock="true" xmlns="sap.m" xmlns:customControl="de.acando.blog.DigitalSignatureBlog.custom.controls">
    	<App id="idAppControl">
    		<pages>
    			<Page title="{i18n>title}">
    				<content>
    					<customControl:DigitalSignature id="digitalSignatureId" 
    					width="70%" borderColor="#eb1af2" borderSize="4px" borderStyle="dotted"
    					fillColor="#ffb630"/>
    				</content>
    			</Page>
    		</pages>
    	</App>
    </mvc:View>
    

 

In die Box die Signatur – Das Dach setzen

Wir haben die Fläche und das Grundgerüst, jetzt fehlt noch das Eigentliche, die Signatur.
Hierfür implementieren wir klassische HTML5-EventListener, mit denen wir darauf “warten”, dass entweder die Maus oder ein Finger unsere Signaturfläche berührt und darauf zeichnen möchte.

Hierfür implementieren wir uns eine Methode, die das Zeichnen der Signatur möglich macht.

_makeAreaDrawable: function (oControl) {
	var canvas = $("#" + oControl.getId())[0]; //This get´s our canvas-element by jQuery
	var context = canvas.getContext("2d"); //Getitng the context of our canvas-area
	var pixels = [];
	var xyLast = {};
	var xyAddLast = {};
	var calculate = false;

	function getCoords(oEvent) {
		var x, y;
		if (oEvent.changedTouches && oEvent.changedTouches[0]) {
			var offsety = canvas.offsetTop || 0;
			var offsetx = canvas.offsetLeft || 0;
			x = oEvent.changedTouches[0].pageX - offsetx;
			y = oEvent.changedTouches[0].pageY - offsety;
		} else if (oEvent.layerX || oEvent.layerX === 0) {
			x = oEvent.layerX;
			y = oEvent.layerY;
		} else if (oEvent.offsetX || oEvent.offsetX === 0) {
			x = oEvent.offsetX;
			y = oEvent.offsetY;
		}
		return {
			x: x,
			y: y
		};
	}
	/**
	 * Eventhandler for when the mouse moves on the specific area without pushing
	 * */
	function onMouseMove(oEvent) {
		oEvent.preventDefault();
		oEvent.stopPropagation();
		var xy = getCoords(oEvent);
		var xyAdd = {
			x: (xyLast.x + xy.x) / 2,
			y: (xyLast.y + xy.y) / 2
		};
		if (calculate) {
			var xLast = (xyAddLast.x + xyLast.x + xyAdd.x) / 3;
			var yLast = (xyAddLast.y + xyLast.y + xyAdd.y) / 3;
			pixels.push(xLast, yLast);
		} else {
			calculate = true;
		}
		context.quadraticCurveTo(xyLast.x, xyLast.y, xyAdd.x, xyAdd.y);
		pixels.push(xyAdd.x, xyAdd.y);
		context.stroke();
		context.beginPath();
		context.moveTo(xyAdd.x, xyAdd.y);
		xyAddLast = xyAdd;
		xyLast = xy;
	}

	/**
	 * Eventhandler for when the mouse moves is pressed on the specific area
	 * */
	function onMouseDown(oEvent) {
		oEvent.preventDefault();
		oEvent.stopPropagation();
		canvas.addEventListener("mouseup", onMouseUp, false);
		canvas.addEventListener("mousemove", onMouseMove, false);
		canvas.addEventListener("touchend", onMouseUp, false);
		canvas.addEventListener("touchmove", onMouseMove, false);
		$("body").on("mouseup", onMouseUp, false);
		$("body").on("touchend", onMouseUp, false);
		var xy = getCoords(oEvent);
		context.beginPath();
		pixels.push("moveStart");
		context.moveTo(xy.x, xy.y);
		pixels.push(xy.x, xy.y);
		xyLast = xy;
	}

	/**
	 * removes the eventhandlers
	 * */
	function removeEventListeners() {
		canvas.removeEventListener("mousemove", onMouseMove, false);
		canvas.removeEventListener("mouseup", onMouseUp, false);
		canvas.removeEventListener("touchmove", onMouseMove, false);
		canvas.removeEventListener("touchend", onMouseUp, false);
		$("body").off("mouseup", onMouseUp, false);
		$("body").off("touchend", onMouseUp, false);
	}

	/**
	 * Eventhandler for when the mouse stops pushing on the specific area
	 * */
	function onMouseUp(oEvent) {
		removeEventListeners();
		context.stroke();
		pixels.push("e");
		calculate = false;
	}
	canvas.addEventListener("touchstart", onMouseDown, false);
	canvas.addEventListener("mousedown", onMouseDown, false);
}

Den Aufruf dieser Methode ergänzen wir in unserem onAfterRendering Eventhandler:

onAfterRendering: function (oEvent) {
		if (sap.ui.core.Control.prototype.onAfterRendering) {
			sap.ui.core.Control.prototype.onAfterRendering.apply(this, arguments); //run the super class's method first
			this._drawSignatureArea(this);
			this._makeAreaDrawable(this);
		}
	},

Das Ergebnis sieht wie folgt aus, wenn wir die App neu starten und in unseren Bereich mit der Maus zeichnen:

Voilà, unser Control lässt uns zeichnen.

Wer beim Control mit Prozentzahlen gearbeitet hat, um die Weite und die Höhe zu setzen, der hat sicherlich bemerkt, dass sich die Signatur seltsam beim Zeichnen verhält. Entweder ist die Linie zu dick oder zu dünn oder die Signatur ist versetzt. Dies liegt daran, dass das canvas-Element “zu früh” rendert und nicht nachrendert, nachdem die komplette View gerendert wurde. In unserer onAfterRendering-Methode müssen wir das rerendern noch dem

onAfterRendering: function (oEvent) {
if (sap.ui.core.Control.prototype.onAfterRendering) {
		sap.ui.core.Control.prototype.onAfterRendering.apply(this, arguments); //run the super class's method first
		this._drawSignatureArea(this);
		this._makeAreaDrawable(this);
		var that = this; //make the control resizable and redraw when something changed
		sap.ui.core.ResizeHandler.register(this, function () {
			that._drawSignatureArea(that);
		});
	}
},
Die Signatur löschen oder als Bild bekommen/speichern – Das Haus wohnlich machen

Nun haben wir unsere Signatur. Wie schön wäre es, wenn unser Control standardmäßig eine Methode implementiert, mit der man die Signatur löschen, oder als Bild bekommen kann.
Hierfür stellen wir nun öffentliche Methoden im Control bereit, die die Funktionalitäten bieten:

Zum Löschen:

clearArea: function () {
	this._drawSignatureArea(this);
},

Um die Signatur als Bild zu bekommen (einmal als JPEG und einmal als PNG):

getSignatureAsJpeg: function () {
	return this._getCanvasAsPicture("image/jpeg");
},

getSignatureAsPng: function () {
	return this._getCanvasAsPicture("image/png");
},

_getCanvasAsPicture: function (sMimetype) {
	var canvas = $("#" + this.getId())[0];
	var image = canvas.toDataURL(sMimetype);
	return image;
},
Das komplette Coding – Einzugsbereit
sap.ui.define(
	["sap/ui/core/Control"],
	function (Control) {
		return Control.extend("custom.controls.DigitalSignature", {
			metadata: {
				properties: {
					width: {
						type: "sap.ui.core.CSSSize",
						defaultValue: "auto"
					},
					height: {
						type: "sap.ui.core.CSSSize",
						defaultValue: "auto"
					},
					borderColor: {
						type: "sap.ui.core.CSSColor",
						defaultValue: "#000000"
					},
					borderSize: {
						type: "sap.ui.core.CSSSize",
						defaultValue: "1px"
					},
					borderStyle: {
						type: "string",
						defaultValue: "none" //none, hidden, dotted, dashed, solid, double, groove, ridge, inset, outset, initial, inherit
					},
					fillColor: {
						type: "sap.ui.core.CSSColor",
						defaultValue: "#FFFFFF"
					},
					signatureColor: {
						type: "sap.ui.core.CSSColor",
						defaultValue: "#000000"
					},
					lineWidth: {
						type: "float",
						defaultValue: 1.5
					},
					lineCap: {
						type: "string",
						defaultValue: "round" //round, butt, square
					}
				},
				aggregations: {}
			},
                        renderer: function (oRm, oControl) {
	                  oRm.write("<canvas class='signature-pad' ");
	                  oRm.writeControlData(oControl);
	                  oRm.addStyle("width", oControl.getWidth());
	                  oRm.addStyle("height", oControl.getHeight());
	                  oRm.addStyle("border", oControl.getBorderSize() + " " + oControl.getBorderStyle() + " " + oControl.getBorderColor());
	                  oRm.writeStyles();
	                  oRm.write("/>");
                        },

			onAfterRendering: function (oEvent) {
				//if I need to do any post render actions, it will happen here
				if (sap.ui.core.Control.prototype.onAfterRendering) {
					sap.ui.core.Control.prototype.onAfterRendering.apply(this, arguments); //run the super class's method first
					this._drawSignatureArea(this);
					this._makeAreaDrawable(this);
					var that = this;										//make the control resizable and redraw when something changed
					sap.ui.core.ResizeHandler.register(this, function () {
						that._drawSignatureArea(that);
					});
				}
			},
			clearArea: function () {
				this._drawSignatureArea(this);
			},

			getSignatureAsJpeg: function () {
				return this._getCanvasAsPicture("image/jpeg");
			},

			getSignatureAsPng: function () {
				return this._getCanvasAsPicture("image/png");
			},

			_getCanvasAsPicture: function (sMimetype) {
				var canvas = $("#" + this.getId())[0];
				var image = canvas.toDataURL(sMimetype);
				return image;
			},

			_drawSignatureArea: function (oControl) {
				var canvas = $("#" + oControl.getId())[0]; //This get´s our canvas-element by jQuery
				var context = canvas.getContext("2d"); //Getitng the context of our canvas-area
				canvas.width = canvas.clientWidth;
				canvas.height = canvas.clientHeight;
				context.fillStyle = oControl.getFillColor(); //Setting the FillColor/FillStyle
				context.strokeStyle = oControl.getSignatureColor(); //Setting the SignaturColor/StrokeStyle
				context.lineWidth = oControl.getLineWidth(); //Setting the SignatureLineWidth
				context.lineCap = oControl.getLineCap(); //Setting the LineCap of the Signature
				context.fillRect(0, 0, canvas.width, canvas.height);
			},

			_makeAreaDrawable: function (oControl) {
				var canvas = $("#" + oControl.getId())[0]; //This get´s our canvas-element by jQuery
				var context = canvas.getContext("2d"); //Getitng the context of our canvas-area
				var pixels = [];
				var xyLast = {};
				var xyAddLast = {};
				var calculate = false;

				function getCoords(oEvent) {
					var x, y;
					if (oEvent.changedTouches && oEvent.changedTouches[0]) {
						var offsety = canvas.offsetTop || 0;
						var offsetx = canvas.offsetLeft || 0;
						x = oEvent.changedTouches[0].pageX - offsetx;
						y = oEvent.changedTouches[0].pageY - offsety;
					} else if (oEvent.layerX || oEvent.layerX === 0) {
						x = oEvent.layerX;
						y = oEvent.layerY;
					} else if (oEvent.offsetX || oEvent.offsetX === 0) {
						x = oEvent.offsetX;
						y = oEvent.offsetY;
					}
					return {
						x: x,
						y: y
					};
				}
				/**
				 * Eventhandler for when the mouse moves on the specific area without pushing
				 * */
				function onMouseMove(oEvent) {
					oEvent.preventDefault();
					oEvent.stopPropagation();
					var xy = getCoords(oEvent);
					xyAdd = xy;
					var xyAdd = {
						x: (xyLast.x + xy.x) / 2,
						y: (xyLast.y + xy.y) / 2
					};
					if (calculate) {
						var xLast = (xyAddLast.x + xyLast.x + xyAdd.x) / 3;
						var yLast = (xyAddLast.y + xyLast.y + xyAdd.y) / 3;
						pixels.push(xLast, yLast);
					} else {
						calculate = true;
					}
					context.quadraticCurveTo(xyLast.x, xyLast.y, xyAdd.x, xyAdd.y);
					pixels.push(xyAdd.x, xyAdd.y);
					context.stroke();
					context.beginPath();
					context.moveTo(xyAdd.x, xyAdd.y);
					xyAddLast = xyAdd;
					xyLast = xy;
				}

				/**
				 * Eventhandler for when the mouse moves is pressed on the specific area
				 * */
				function onMouseDown(oEvent) {
					oEvent.preventDefault();
					oEvent.stopPropagation();
					canvas.addEventListener("mouseup", onMouseUp, false);
					canvas.addEventListener("mousemove", onMouseMove, false);
					canvas.addEventListener("touchend", onMouseUp, false);
					canvas.addEventListener("touchmove", onMouseMove, false);
					$("body").on("mouseup", onMouseUp, false);
					$("body").on("touchend", onMouseUp, false);
					var xy = getCoords(oEvent);
					context.beginPath();
					pixels.push("moveStart");
					context.moveTo(xy.x, xy.y);
					pixels.push(xy.x, xy.y);
					xyLast = xy;
				}

				/**
				 * removes the eventhandlers
				 * */
				function removeEventListeners() {
					canvas.removeEventListener("mousemove", onMouseMove, false);
					canvas.removeEventListener("mouseup", onMouseUp, false);
					canvas.removeEventListener("touchmove", onMouseMove, false);
					canvas.removeEventListener("touchend", onMouseUp, false);
					$("body").off("mouseup", onMouseUp, false);
					$("body").off("touchend", onMouseUp, false);
				}

				/**
				 * Eventhandler for when the mouse stops pushing on the specific area
				 * */
				function onMouseUp(oEvent) {
					removeEventListeners();
					context.stroke();
					pixels.push("e");
					calculate = false;
				}
				canvas.addEventListener("touchstart", onMouseDown, false);
				canvas.addEventListener("mousedown", onMouseDown, false);
			}
		});
	});
Zusammenfassung – Was haben wir gelernt?

Wir haben unser eigenes Control erstellt, das wir nun jederzeit in andere Views einsetzen können und das auch direkt Eigenschaften und Methoden bereitstellt. Die Eigenschaften und Methoden lassen sich nach belieben erweitern und an spezifische Bedürfnisse anpassen.

Bis zum nächsten Blog! Möchtet ihr noch mehr über eigene Controls erfahren? Dieser Blog könnte hilfreich sein!

Schon gesehen?
Arbeiten als SAPUI5-Entwickler bei Acando!

Über den Autor

Tim Schomaker

4 Kommentare zu “Digitale Unterschrift als Control in SAPUI5”

  • Mathias Körner sagt:

    Hallo Tim,

    toller Blog. Der hat mir extrem weitergeholfen, weil ich an der Stelle eine App entwickeln muß, um eine Unterschrift zu erfassen.
    Was hier leider nicht geht ist das Control in einem Popup darzustellen. Hast Du das mal versucht? Ich habe alle möglichen Varianten probiert, aber es lässt sich nicht darstellen bzw. wenn man überhaupt etwas sieht, dann nur in der linken, oberen Ecke einen ganz kleinen Ausschnitt.
    Ausserdem ist es auch nicht möglich das Control per Controller ein- bzw. auszublenden. Das wird nicht angezeigt.
    Was mir noch gefehlt hat, was aber hier schön wäre, ist eine Möglichkeit Events auszulösen. Das habe ich nach einiger Knobelei aber hinbekommen.
    Ansonsten eine tolle Anleitung.

    • Tim Schomaker sagt:

      Hallo Mathias,

      vielen Dank für dein Feedback und deine Fragen.

      Die digitale Signatur lässt sich natürlich auch in einem Popup verwirklichen. In dem View-Controller wäre dieses Coding beispielsweise denkbar, ausgelöst durch einen Button, der das Event “onOpenPopup” triggert.

      pressDialog: null,
      onOpenPopup: function (oEvent) {
      if (!this.pressDialog) {
      this.pressDialog = new sap.m.Dialog({
      title: 'Digitale Signatur im Popup',
      content: new DigitalSignature({
      height: "100px",
      width: "600px",
      id: "digitalSignaturePopupId",
      borderStyle: "solid"
      })
      });

      //to get access to the global model
      this.getView().addDependent(this.pressDialog);
      }
      this.pressDialog.open();
      }

      Dadurch lässt sich die digitale Signatur in einem Popup einbinden. Gegebenenfalls muss das das DigitalSignature Control angepasst werden in der Methode getCoords(), damit die Unterschrift auch in die passende Box gezeichnet wird.

      Zum Ein-/Ausblenden des Controls per Controller habe ich Folgendes implementiert.

      CustomController: Erweiterung der Properties und der Methode renderer

      visibility: {
      type: "string",
      defaultValue: "visibile" //visibile, hidden
      }


      oRm.addStyle("visibility", oControl.getVisibility());

      Im ViewController folgende Methode, die auf einen entsprechenden Button hört:


      onShowHide: function (oEvent) {
      var oDigitalSignature = this.getView().byId("digitalSignatureId");
      if (oDigitalSignature.getVisibility() === "hidden") {
      oDigitalSignature.setVisibility("visibile");
      } else {
      oDigitalSignature.setVisibility("hidden");
      }
      },

      Im Prinzip wird dem Canvas HTML5 Element das CSS-Attribut “visible” hinzugefügt, dass dann auch zur Laufzeit geändert werden kann.
      Da sind im Rahmen von HTML5 derzeit soweit UI5 es ermöglicht keine Grenzen gesetzt.

      Ich hoffe, dass dir diese Punkte weiterhelfen.
      Bei weiteren Fragen kannst du dich gerne wieder melden.

  • Mathias Körner sagt:

    Hi Tim,
    ich muß mich nochmal melden.
    Vom Prinzip her funktioniert das wunderbar, solange ich die App in einem normalen Browserfenster laufen lasse.
    Sobald ich aber mein App im Fiori-Client auf einem mobilen Device laufen lasse, kann ich zwar die Unterschrift erfassen, aber der Button, den ich zum Speichern auf der umgebenden Page habe reagiert nicht mehr auf das Event “press”. Das scheint am EventListener des canvas zu liegen.
    Hast Du da eine Idee dazu?
    Im Browser funktioniert das.

    Danke

    Mathias

    • Mathias Körner sagt:

      Hi Tim,

      das Problem waren 2 zusätzliche Zeilen Code, die ich versehentlich eingebaut habe.
      Das hat sich also mittlerweile erledigt und funktioniert.

      Gruß

      Mathias

Kommentieren

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

34 − = 30