How can I restrict a text edit field to only specific characters?

21 views (last 30 days)
Using the App Designer in R2020b, I have a text edit field that I want to restrict to a set of specific characters. I am trying with the following code in the app:
% Value changing function: EditField
% Value Changing function triggers on every key press.
function EditFieldValueChanging(app, event)
% Allow only "M" and "W" characters - case insensitive - but allow spaces
% between them.
allowedChars = 'mMwW ';
% Event.Value is the new character array after the user's typing. Keep
% only those characters that are in allowedChars.
allowedEdit = event.Value(ismember(event.Value, allowedChars));
% Set the control's Value to the filtered text.
app.EditField.Value = allowedEdit;
% Show the input and the filtered output, as diagnostics.
disp({event.Value app.EditField.Value})
% Using drawnow() should cause the control to update to display its
% Value, but it doesn't.
This code should ensure that if the user types a disallowed character, it vanishes from the edit field immediately. In fact, all typed characters appear in the field until a valid character is typed - then all the disallowed characters vanish leaving only the "correct" value. Below is some example command window output, showing {event.Value}, {app.EditField.Value} and (as a comment) what is seen in the edit field. We see that the Value Changing function is indeed running after every character, but the app display is not updating.
{'m'} {'m'} % m
{'mw'} {'mw'} % mw
{'mw5'} {'mw'} % mw5 Should be mw
{'mw5M'} {'mwM'} % mwM
{'m6wM'} {'mwM'} % m6wM Should be mwM
{'m6wWM'} {'mwWM'} % mwWM
As an additional annoyance, the cursor goes to the end of the edit field after the last test, even though the last typing ("W") was done in the middle of the string. That will likely confuse a user.
If the user clicks outside the box, or presses enter, the filtering function is triggered.
I'm not sure what's wrong here. I may have misunderstood how values update on app components, or how drawnow() works. Is there a better way to do what I want? My absolute ideal would be something that works like the numeric edit field (if you try typing a letter the border turns red, and you get a tooltip saying "Value must be numeric").

Answers (1)

Mario Malic
Mario Malic on 19 Mar 2021
Hi David,
I haven't used ValueChangingFcn, but something like this should probably work.
allowedChars = 'mMwW ';
if ~any(app.EditField.Value(end) == allowedChars)
app.EditField.Value(end) = [];
Regarding the drawnow, it's usable only for graphic objects like axes, figures etc.
Mario Malic
Mario Malic on 22 Mar 2021
Edited: Mario Malic on 22 Mar 2021
My bad, I should have been more descriptive in my answer. I haven't used this type of callback myself - this is what I ment.
Anyways, turns out that there are issues with my example: when you want assign text to property Value, callback won't be executed, and this is a bit problematic.
Even though this task seems simple, I am not sure if it is. In here, fieldText is property that accumulates the allowed letters. This is not completely working, if you delete a letter, this callback will check again the last letter of event.Value and it will add it if it's allowed one. Probably this could be done with events and listeners. When the Value property is changed, assign app.fieldText to it. However I have never tried to work with it.
Edit: since this is not an answer, I'll move it to the comments soon
properties (Access = public)
allowedChars = 'mMwW '; % Description
fieldText = '';
% Callbacks that handle component events
methods (Access = private)
% Value changing function: EditField
function EditFieldValueChanging(app, event)
if isempty(event.Value)
app.fieldText = '';
if any(ismember(event.Value(end), app.allowedChars))
app.fieldText(end+1) = event.Value(end);

Sign in to comment.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!