If node’s property validation fails, the node will be flagged with an error. The details of the error can be checked with the tooltip of the node. But, it may not be meaningful to the user in some case because the information in the tooltip is internal property name.
So, I would like to propose a message to be displayed in the tooltip can be specified within the property definition.
Proposal:
A property definitions can have a validationMessage property. If the property validation fails, the value of the validationMessage property is displayed instead of property name in node's tooltip.
But a single field can contain lots of data. For example an array of objects that are being displayed inside an editableList. Such data can be wrong due to multiple different reasons: duplicate names, more than 10 rows, or whatever.
In this case it might be usefull if we were able to show the particular error, which means the validationMessage should refer to a callback function (that generates a validation message). On the other hand perhaps not, because then you would have to repeat your entire validation logic in that second function again.
So perhaps that is a really bad idea, and your static text is indeed much better...
Bart
This would be useful in other areas too. e.g. for field tooltips, form labels, friendlier debug messages, automation (and many more places I cannot think of right now).
Then the nodes triangle tip could be a concatenation of " - Invalid " + op1.friendlyName
We also have this item to allow a node to provide a validate function that isn't tied to a specific property - as sometimes the validation has to be done by considering the overall configuration and not one property at a time.
The question is then how to provide better feedback to the user when the validation fails (as highlighted in this item on the backlog
Some comments on the ideas proposed so far:
validationMessage: "a message"
If there are multiple reasons why a value could be invalid, a single message won't help the user understand what is wrong.
validationMessage: function() {}
This would allow for more flexible messages - but it would require duplicate code to work out what value to return
friendlyName
For this use case, it wouldn't help communicate what was wrong with the value. There may well be other usability improvements that such a field would bring, but I would suggest not entangling them here.
What I think I had in mind for this area was actually to modify the existing validate property.
Currently it returns true or false based on whether the field is valid.
We could extend that to:
return true - valid (as-is behaviour)
return false - invalid (as-is behaviour)
return "string" - invalid with given error message
The downside is backward compatibility - installing a newer node in old Node-RED and having the validate function return a string that looks like true when it actually means false
So another option would be for the validate function to throw an error with the message in. The existing Node-RED code already catches the error and logs it in the browser console:
if (valid && "validate" in definition[property]) {
try {
valid = definition[property].validate.call(node,value);
} catch(err) {
console.log("Validation error:",node.type,node.id,"property: "+property,"value:",value,err);
}
}
That could be modified to also set valid to false if an error is thrown and to capture the message from the error for reporting back to the user.
Could that be made to work if the message included variables? Could the message access a variable from the validation function? Or perhaps better (but more complex), could additional properties be allowed on the defaults property that were accessible from within the validation function?
Agree though maybe for a slightly different reason. I think that having the simple boolean response is nice and clean from a development perspective.
Sounds usable though more complex from a usability perspective maybe(?) than properties on the default? Quite probably simpler from a core development perspective though?
I disagree. I don't think you can call throw new Error("only cats allowed") is more complex then return false for anyone with even passing experience writing JavaScript code.
It feels quite a natural way for a function to "fail" with an associated message.
A message catalogue identifier is a string. We'd do the same thing we do elsewhere - check for a message in the node's catalog, or fall back to the string as is.
I have a concern that exception approach also have a compatibility issue when a newer node is used on existing Node-RED because throwing Error only display the message on browser console.
From a flexibility point of view, I think it's a good idea to change the API of the validate function as you suggested. However, I think it may be necessary to use the old and new API properly with an additional argument to validator. In that case, I prefer the idea returning the message string.
For simple cases, it would be nice to be able to specify an additional message string to RED.validators functions.
@knolleary Any thought on this?
If there is no particular issues, I would like to make a PR based on the method which validate function returns message string.
This has stalled because of the question of backward compatibility.
The editor currently uses the returned value from the validate function as a boolean - a true-like value is valid, a false-like value is invalid.
If we return a string to mean 'invalid', existing versions of Node-RED will treat that as valid.
So the question has been whether there is a backward compatible way to return this extra information (the message) whilst also indicating invalid. Unfortunately JavaScript does not have a false like object that can have properties.
And we've already covered that throwing an error would not work due to the way that is currently handled.
Another way of thinking about it is whether the validate function itself can know whether it should return false or a string. That puts the responsibility on the node author to add that logic in, which is not ideal, but would help solve it.
For example:
validate: function(value, messageSupported) {
// decide if value is valid
if (valid) {
return true
} else {
return messageSupported?"This is invalid":false
}
}
The built-in RED.validators.* functions would implement this under the covers, so that they could take an optional second message argument as you suggest and do the right thing.
It isn't the prettiest solution, but it's the most reasonable way I can think of keeping it backward compatible.