Autofill option in text field component vision

Hi Guys,

When writing text in the text field component in the vision the autofill option opens. autofill option gets from the database. Can you suggest how to fix this?

Ignition 8.1.17
MSSQL server 16

Thanks,
Priyanka

I am not familiar with this feature. Is this something you are wanting to create, or have you already created it, but you are having some kind of problem?

@justinedwards.jle Thanks for the replay.

I have written some script in the text field KeyPressed but I have no idea how to display a sorted list in the text field when I write any key in the text field.

if len(event.source.text) > 1:
autofillQuery = "SELECT CONCAT(FirstName,', ',LastName) AS Name FROM Flexible WHERE FistName LIKE '{event.source.text}%'"
database = "Test"
autofillpyDataSet = system.db.runQuery(autofillQuery, database)
autofillnormalDataset = system.dataset.toDataSet(autofillpyDataSet)
options =
if autofillnormalDataset != 0:
for rowIndex in range(autofillnormalDataset.rowCount):
Name = autofillnormalDataset.getValueAt(rowIndex, 'Name')
options.append(Name)
print options

Come to think of it, I did create something like this before when I was playing around with a multi select dropdown problem here in the forum:

As you can see in the video, the template has a predictive text feature. I believe I layered a label underneath the text field, and made the text field background transparent. The predictive label is then populated with scripting on one of the keypress events. It wouldn't be difficult to add a special key condition to the keyReleased or keyPressed event to move the label text into the actual text field.

I've also generated a popup menu from a text field component that simulates the functionality of dropdown. Perhaps some or all of the code from this example could help you with what you are trying to accomplish:

Yes. My requirement same as this but the only difference in my case is no dropdown. In my case using the text field component.

If you import either of those templates, I believe you'll find that in both cases I have elected to use a text field instead of a dropdown. In the first example, I am using the text field to control the visibility of a power table that is positioned underneath the text field. If you wanted to adapt that template to your usage case, simply delete the power table and all scripts involved in populating it.

In the second example, I am using a text field to generate a popup menu that I position underneath the the text field. I populate it with either a jlist or jmenuitems depending on whether or not I am embedding a scroll pane. Of course, for your usage case, the popup menu could be positioned anywhere in relation to the text field.

@justinedwards.jle Thank you so much.

I will try.

I was able to accomplish this. My text field has a custom property called data. Here is the test contents:
image

Here is the result:

Here is the component:
autoFillTextField.zip (4.5 KB)

The enter key triggers the auto complete

4 Likes

Waa Great. Thank you so much @justinedwards.jle. You are a very helpful person.

2 Likes

This looks like an idea I want to use, so I developed this a little further. I added a string custom property to the textfield called predictedText as part of a case mismatch correction, and I added a public Boolean custom property to the template itself called autoComplete to make the autocomplete function optional.

In the prototype, I chose not to make the dataset search case sensitive because I imagined that it would make the function more convenient for users, but when a case mismatch occurred, a slight misalignment would appear between the predicted text and the actual text, so I added a function that corrects this. Another problem that I observed was that the caret position moved to zero after the autocomplete was finished. I added code that puts the cursor back at the end of the string after auto complete.

Lastly, I also wanted to use the tab key, but when I tore apart the multiselect template to create the above proof of concept, I was having trouble finding an intuitive way to consume the tab input, so I just went with the enter key. While I still haven't found a traditional way of doing this, I was able to accomplish the same end using the focusLost event handler, so if you would prefer to use the tab key, that is an option.

Here is the updated keyReleased script:

from java.awt.event import KeyEvent, KeyAdapter
textfield = event.source
predictiveText = event.source.parent.getComponent('predictiveText')
autoCompleteField = event.source.parent
labelIndex = 1 if event.source.parent.Data.columnCount > 1 else 0
def getMatchedCase(text, predictedText):
	caseMatchedText = predictedText
	if len(predictedText) > len(text):
		for letter in range(len(text)):
			if text[letter] != predictedText[letter]:
				caseMatchedText = caseMatchedText[:letter] + text[letter] + predictedText[letter+1:]
	return caseMatchedText
if autoCompleteField.autoComplete:
	if event.getKeyCode() == KeyEvent.VK_ENTER and autoCompleteField.autoComplete:
		textfield.autofill(event)
	else:
		data = textfield.internalData
		text = textfield.text
		textNotFound = True
		for row in range(data.rowCount):
			label = data.getValueAt(row, labelIndex)
			if text.lower() in str(label).lower()[0:len(text)]:
				predictedText = str(data.getValueAt(row, labelIndex))
				textfield.predictedText = predictedText
				predictiveText.text = getMatchedCase(text, predictedText)
				textNotFound = False
		if textNotFound or len(text) < 2:
			predictiveText.text = ''

Note that I've changed the name of 'Text Field 1' to 'predictiveText'

For my purposes, I moved part of the script into a custom method that I call autofill that I can call from either the keyReleased or focusLost event handlers. In this way, I can trigger the auto complete from both the tab and enter key without having the same code in two places. Here is the code for the autofill custom method:

#def autofill(self, event):
	def setCaretPosition():
		textfield.setCaretPosition(len(textfield.text))
	autoCompleteField = event.source.parent
	textfield = event.source
	predictiveText = autoCompleteField.getComponent('predictiveText')
	textfield.text = textfield.predictedText
	predictiveText.text = textfield.predictedText
	textfield.requestFocusInWindow()
	system.util.invokeLater(setCaretPosition)

Note that this custom method requires an event parameter

Here is the focusLost script that controls tab key actions:

textfield = event.source
autoCompleteField = event.source.parent
predictiveText = event.source.parent.getComponent('predictiveText')
if str(event.cause) == 'TRAVERSAL_FORWARD' and autoCompleteField.autoComplete and len(textfield.text) != len(predictiveText.text):
	textfield.autofill(event)

The first time the tab key is pressed, the text field retains focus, and auto completes. However, if the auto complete has already occurred or is not an option due to no prediction available, the tab key performs normally and traverses the focus to the next focusable component.

4 Likes

@justinedwards.jle Thank you so much.

Explain everything in detail and very helpful.

1 Like

image

A fully developed version of this is now available on the exchange:

Auto Complete Text Field

4 Likes

Do we have similar thing in perspective by any chance?