Prevent edit-text widget from allowing 0 or negative values (type=number)

As the title says: is there a way to limit a <$text-edit type=number> widget to positive, non-zero values only? (in other words set a min value)

Unfortunately $edit-text doesn’t currently support HTML <input> attributes like step, min, and max, though I agree this would be a nice upgrade!

What you could do is display an error message when the field input doesn’t match your desired specifications. For instance:

<$edit-text type=number field=myField />
<% if [<currentTiddler>get[myField]compare:number:lteq[0]] %>
@@color:red; Please input a number greater than 0!@@
<% endif %>

Note that I’m using <currentTiddler>get[myField] rather than simply {!!myField} because get[myField] only returns a result if myField exists and is non-blank. You could substitute {!!myField}!is[blank] or {!!myField}!match[]] for the same result, but I tend to prefer get because it’s easier to substitute a variable as the parameter.

Damn! From this old thread back in 2017, where @EricShulman seemed to have solved this, I really thought there was a way but it wasn’t documented :stuck_out_tongue_winking_eye:

Good find! It looks like that PR never happened, though I don’t quite understand the arguments against it.

The code additions I suggested back in 2017 never made it into the core, and I don’t see any PR for them, but they are still valid in the current release (v5.3.6), and you can apply them in your own wiki, like this:

in $:/core/modules/editor/factory.js, in EditTextWidget.prototype.execute(), after this line:

this.isFileDropEnabled = this.getAttribute("fileDrop","no") === "yes";

add these lines:

this.editRangeMin  = this.getAttribute("min",0);
this.editRangeMax  = this.getAttribute("max",100);
this.editRangeStep = this.getAttribute("step",1);

and in $:/core/modules/editor/engines/simple.js, in SimpleEngine(options), after this:

if(this.widget.isDisabled === "yes") {
	this.domNode.setAttribute("disabled",true);
}

add these lines:

if(this.widget.editRangeMin)  {
	this.domNode.setAttribute("min",this.widget.editRangeMin);
}
if(this.widget.editRangeMax)  {
	this.domNode.setAttribute("max",this.widget.editRangeMax);
}
if(this.widget.editRangeStep) {
	this.domNode.setAttribute("step",this.widget.editRangeStep);
}

enjoy,
-e

3 Likes

I added the lines as you instructed, then proceeded to write my textwidget like this:

<$edit-text tiddler=<<spellbook>> index=<<spell>> type=number min="0" default="1" size="2" tag=input/>

… and it works :slight_smile:

(I did refresh the page to reload js stuff)

Maybe you could, alternatively, use the inputActions of the EditTextWidget to run a macro on each change that checks if the value is greater than zero. If it is, then use an ActionSetfieldWidget to set it to a valid value. This way you wouldn’t need to overwrite core widgets.