What is the correct approach to have a default hint text for a TextBlock similar to HTML 5 placeholder attribute?
Thanks
Alain
What is the correct approach to have a default hint text for a TextBlock similar to HTML 5 placeholder attribute?
Thanks
Alain
Actually, I think you are asking about the placeholder attribute of an <input>
element in a text editor, not about the appearance of a TextBlock visual object in GoJS.
You can certainly customize your text editor however you like. Please read:
GoJS HTML Interaction -- Northwoods Software.
See also how the standard editor is implemented, at: https://gojs.net/latest/extensions/TextEditor.js. It’s demonstrated at: HTMLInfo Text Editor
Yes I was asking similar to the placeholder attribute of input or textarea.
From your link I get it to understand that it is not available in the base TextBlock but we can implement a custom text editor like in TextEditor.js and there set the html placeholder to the value that we want.
That’s correct.
This would be a great feature request IMO. Can we add a placeholder
option for TextBlock
which just adds placeholder
attribute to its underlying textarea
? That would be very helpful.
What do you think Walter?
I’ll look into it. I suspect it can be implemented easily enough as an extension.
I actually looked into TextEditor extension but it’s very similar to the one already bundled with gojs:
So I guess we just need a few lines to read the option from gojs and add a placeholder here. That way we don’t have to ship an extra extension or fall behind any updates you guys make on the TextBlock
.
Or I think an even better solution would be a way to give us access to the underlying DOM element so we can do whatever we want with it.
During in-place text editing, this expression will get you the <textarea> element:
myDiagram.toolManager.textEditingTool.currentTextEditor.mainElement
Try this:
class PlaceholderTextEditingTool extends go.TextEditingTool {
doActivate() {
super.doActivate();
const ta = this.currentTextEditor.mainElement;
if (ta) ta.placeholder = "enter label text";
}
}
Install it when initializing the Diagram:
new go.Diagram("myDiagramDiv", {
textEditingTool: new PlaceholderTextEditingTool(),
. . .
})
As you pointed out, this only appears when user is actively editing the text and deletes the entire text.
The purpose of placeholder
is to hint what this input is for before the input gets any focus and keyboard input. So I don’t see this as a solution to be honest.
Sorry, then I’m misunderstanding why you talked about the <textarea>'s placeholder.
Until the user starts in-place text editing, no text editor is visible. In other words, there’s no <textarea> visible to show a placeholder or anything else.
If you want a TextBlock to show some text, perhaps in gray or italics, just set or bind the TextBlock.stroke or TextBlock.font along with the TextBlock.text message that you want to show.
Oh you’re right about the textarea
not being in the DOM. The main problem we’re trying to fix is, even if I bind the stroke and make the font look italic as soon as the user starts editing the initial text is the value. So user needs to delete it and then start typing.
Compare that to an actual text input where the placeholder
text is gone once it gets focused.
<!DOCTYPE html>
<html>
<head>
<title>Text Editor with Hint</title>
<!-- Copyright 1998-2024 by Northwoods Software Corporation. -->
</head>
<body>
<div id="myDiagramDiv" style="border: solid 1px black; width:100%; height:600px"></div>
<textarea id="mySavedModel" style="width:100%;height:250px"></textarea>
<script src="https://unpkg.com/gojs"></script>
<script id="code">
class CustomTextEditingTool extends go.TextEditingTool {
doActivate() {
super.doActivate();
const ta = this.currentTextEditor.mainElement;
if (ta.value === Hint) ta.value = "";
}
doSuccess(oldstr, newstr) {
const tb = this.textBlock;
tb.stroke = newstr ? "black" : "gray";
tb.font = newstr ? "10pt sans-serif" : "italic 10pt sans-serif";
if (!newstr) tb.text = Hint;
}
}
const Hint = "Enter some text here";
const myDiagram =
new go.Diagram("myDiagramDiv", {
textEditingTool: new CustomTextEditingTool(),
"undoManager.isEnabled": true,
"ModelChanged": e => { // just for demonstration purposes,
if (e.isTransactionFinished) { // show the model data in the page's TextArea
document.getElementById("mySavedModel").textContent = e.model.toJson();
}
}
});
myDiagram.nodeTemplate =
new go.Node("Auto", { width: 140, minSize: new go.Size(140, 40) })
.add(
new go.Shape({ fill: "white" })
.bind("fill", "color"),
new go.TextBlock(Hint, { stroke: "gray", font: "italic 10pt sans-serif", editable: true })
.bindTwoWay("text", "text", t => t ? t : Hint, v => v === Hint ? "" : v)
);
myDiagram.model = new go.GraphLinksModel(
[
{ key: 1, color: "lightblue" },
{ key: 2, color: "orange" },
{ key: 3, color: "lightgreen" },
{ key: 4, text: "", color: "pink" }
],
[
{ from: 1, to: 2 },
{ from: 1, to: 3 },
{ from: 2, to: 2 },
{ from: 3, to: 4 },
{ from: 4, to: 1 }
]);
</script>
</body>
</html>
Awesome. This seems to be working. Thanks Walter. As an alternative and potential feature request, if you provide onFocus
for the TextBlock
, think this will be a lot simpler.
Thanks again.