Pick List Question. Update List via a script or trigger a form lookup

Tap Forms – Organizer Database App for Mac, iPhone, and iPad Forums Script Talk Pick List Question. Update List via a script or trigger a form lookup

Viewing 20 reply threads
  • Author
    Posts
  • March 29, 2021 at 11:00 AM #43968

    johnny_law
    Participant

    I know there are some methods exposed to the pick list object. I have not got any success using it. I have the iOS version of Tap Forms 5.

    I am working on a movie database. I have a need to have a pick list of all actors that are in the current record movie.

    I have written a script that gets the actors from an online service. It deletes all rows from a hidden actor form, then populated the form with actors from the movie which is the current record.

    The actors Pick List gets it’s values from the Actors Form. The problem is the Pick List seems to only populate with the updated values on document load.

    Is there any way of triggering a Pick List to populate progamically? This would solve my problem.

    Or am I going about this all wrong?

    If there was a way to alter the dictionary object associated with Pick List that would work too. However I have not been able to get a Pick List object to return a dictionary, all I get is an undefined object. I know I am doing something wrong. An example of using the Pick List object and methods would be great.

    April 1, 2021 at 10:11 PM #43996

    Brendan
    Keymaster

    Hi Johnny,

    Sorry for my delayed response.

    Improving the JavaScript API to support more Pick List functions such as pickList.addValue('Sci Fi') or pickList.addValues(some_values_array); is on my toDo list.

    But I haven’t worked on that yet. In the meantime, something like this will work, but it does seem like you still have to close the document and re-open it for the new values to appear:

    function AddToPickList() {
    
    	var pick_list = document.getPickListNamed('Condition');
    	var pick_list_values = pick_list.values;
    	
            // print the current set of values. You can see the dictionary format you need. You can optionally provide a <code>valueColour</code> (yes, Canadian spelling) property key too. Use the colour format you see.
    	console.log(JSON.stringify(pick_list_values));
    
    	var new_value = {"value" : "My New Pick List Value"};
    
            // add the new value to the values array.
    	pick_list_values.push(new_value);
    
            // reset the list of values with the array that contains the new value
    	pick_list.values = pick_list_values;
    	
            // saving on the pick_list
    	pick_list.saveChangesInDatabase();
    	
            // log our new set of values.
    	console.log(JSON.stringify(pick_list_values));
    
    }
    
    AddToPickList();

    In a future update I’ll add a better API for Pick Lists. I’ve tested this and it does work.

    April 2, 2021 at 10:57 PM #44006

    johnny_law
    Participant

    Thanks Brendan,

    This helps me understand the picklist programming. I’ll play around with it.

    Unfortunately it needs a document close/open. I really need an ability to have a dynamic picklist on a record by record basis.

    BTW I have really enjoyed the increase in power with scripting in Tap Forms. My favorite app.

    April 3, 2021 at 8:39 AM #44021

    Sam Moffatt
    Participant

    You can use the Prompter to build a popup dialog with a custom pick list in it that you bind to a keyboard shortcut. The prompter lets you provide any arbitrary set of values to the list it has and then you can select from there. It does mean you step outside of the pick default layout interface and you’re limited to one style but it should work for what you need.

    April 3, 2021 at 4:16 PM #44039

    johnny_law
    Participant

    Sam that is a great idea, but I don’t have a Mac and am using the IOS version. That is the issue, how do I get the pop-up (no keyboard shortcuts). I have also had difficulty with the prompter and async functions. But that is because I am a novice that knows enough to cause trouble.

    Using a checkmark field is an option but I always have issues with the screen updating after execution.

    I have been putting a date/time field in that causes a form script to run when it is undefined. After the script runs it sets the current date/time

    April 4, 2021 at 11:12 AM #44040

    Sam Moffatt
    Participant

    Missed the iOS bit, unfortunately no keyboard shortcuts there for scripts though that’d be cool addition as Apple positions the iPad more and more towards being keyboard friendly. It’s definitely a few taps to run a form script if you want to take that approach but it sounds like the checkbox approach mostly works for you. If you tap the currently selected record again it should refresh the display.

    The prompter stuff for your use case isn’t too bad. You need to split it up into two pieces: getting the list of items for the pick list and handling the popup event. I gather you have a way of figuring out the set of actors and then all you need to do is feed that into the prompter.

    Here is something that should do the trick, you’ll need to change the setFieldValue line to match you field name and provide an implementation for getActorNames:

    var actorName;
    
    function callbackFunction() {
    	if (actorName) {
    		console.log(actorName);
    		record.setFieldValue('fld-actorname', actorName);
    		document.saveAllChanges();
    	}
    }
    
    function getActorNames() {
    	return ['Actor 1', 'Actor 2', 'Actor 3'];
    }
    
    function popup() {
    	let prompter = Prompter.new();
    	prompter.addParameter('Actor: ', 'actorName', 'popup', getActorNames())
    		.show('Select Actor', callbackFunction);
    }
    
    popup();
    
    April 5, 2021 at 4:45 PM #44044

    johnny_law
    Participant

    I am going to give your suggestion a try. It may work. I have decided to keep all the actors, and their info in their own form and link it to the movie on a many-to-many relationship. Though I only want to track a select few. The pop up will be the solution of picking the actors that I want to track. I can unlink the ones that are not selected.

    Thanks Sam for the code.

    April 5, 2021 at 6:52 PM #44045

    johnny_law
    Participant

    Is there any option to have a multi-select prompter? Don’t know where the parameters are documented.

    April 5, 2021 at 7:44 PM #44047

    Sam Moffatt
    Participant

    I don’t think there is a mutliselect prompter, the documentation in general is on the Javascript API page. The prompter stuff is relatively new in the grand scheme of things and not fully fleshed out, it’s a step towards more programmatic UI interaction.

    April 5, 2021 at 11:56 PM #44050

    Brendan
    Keymaster

    Ya, there’s no multi-select Prompter function. Sorry about that.

    April 8, 2021 at 8:59 PM #44089

    johnny_law
    Participant

    I’ve done everything that I can think of. I can not get the prompter to fill the variables.

    Using Tap Forms Version 5.3.19 (1041) on iOS 14.4.2 on an iPhone 12 Pro.

    I copied and pasted code from the Tap Forms Mac Manual, from snippets of code. Even very simple examples but variables stay as undefined.

    I have changed where the var statements are located before or after the call back function. Nothing!

    What could I be doing wrong? A sample of an easy prompter code I can’t get to work:

    var note;
    var datetime;
    
    function callbackFunction() {
    	console.log('Callback');
    	console.log('Note:');
    	console.log(note);
    	console.log('Date Time:');
    	console.log(datetime);
    }
    
    let prompter = Prompter.new();
    prompter.addParameter('Note:', 'note', 'text')
    prompter.addParameter('DateTime:', 'datetime', 'date_time')
    prompter.show('input info', callbackFunction);
    April 8, 2021 at 11:50 PM #44090

    Daniel Leu
    Participant

    The issue you encountered is that the prompter function is not blocking. So when you access the variable after the prompter call, this access happens before you have a chance to enter anything.

    I was struggling with this for a while when it was first introduced. This is what I use now:

    
    function textPrompter(title, text="") {
    	return new Promise(function(resolve, reject) {
    		let prompter = Prompter.new();
    		prompter.cancelButtonTitle = 'Cancel';
    		prompter.continueButtonTitle = 'Continue';
    		prompter.addParameter(text,'prompterVar')
    		.show(title, ((status) => { 
    			if (status == false || prompterVar == undefined) {
    				reject('Cancel');
    			} else {
    				resolve(prompterVar);
    			}
    		}));
    	});
    }
    
    async function prompterTest() {
    	// Check textPrompter
    	try {
    		await textPrompter("Title", "Enter text") 
    		console.log(prompterVar + " entered");		
    	} catch (errorText) {
    		console.log('cancelled textPrompter: ' +errorText);
    	} finally {
    		console.log(scriptName+": Script finished at " + new Date);
    	}
    }
    	
    prompterTest();
    

    Hope this helps!

    April 9, 2021 at 12:34 PM #44095

    johnny_law
    Participant

    Thanks Daniel, that does work! I’ll try to modify this to meet my needs.

    April 9, 2021 at 1:14 PM #44097

    Daniel Leu
    Participant

    Perfect!

    April 9, 2021 at 8:43 PM #44102

    Sam Moffatt
    Participant

    I tried your original sample code myself on an iPad and iPhone which worked properly on both. I’m curious why it wasn’t working for you because it worked for me as is in a form script.

    April 9, 2021 at 9:19 PM #44105

    johnny_law
    Participant

    I was using a Form script also and could not get anything but ‘undefined’. But Daniels async function call works great.

    Very odd. It would be more simple if the original code worked.

    April 9, 2021 at 10:17 PM #44108

    Sam Moffatt
    Participant

    I also just gave the sample off API page a spin on my phone and it printed out to the console the input as expected. I’m curious if you can take a screenshot of the console in the script editor on your phone after you’ve filled in a few things just to see what it looks like?

    April 10, 2021 at 8:20 AM #44112

    Daniel Leu
    Participant

    Sam, the example works. I think the issue is how you use it. For example, accessing the prompter variables after the prompter call like this

    ....
    .show('Message prompt', callbackFunction);
    
    console.log(value_1);
    

    Due to the non-blocking behavior of the prompter, this doesn’t work.

    April 10, 2021 at 12:37 PM #44118

    johnny_law
    Participant

    Ok, I know I’m dense, but I fell upon the reason I was getting “undefined” in the snippet I posted earlier and the copy and paste of Brendan’s example in the Mac Manual.

     var output = function printOut(continued) {
            if (continued == true) {
                console.log(username + ", " + password + ", " + email_address + ", "
     + other_field + ", " + genre);
            } else {
               console.log("Cancel button pressed.");
    } }
    //  var username;
    //  var password;
    //  var email_address;
    //  var other_field;
    //  var genre;
     var genres = ['Action & Adventure', 'Comedy', 'Drama', 'Horror', 'Science Fiction'];
     let prompter = Prompter.new();
     prompter.cancelButtonTitle = 'No Thanks';
     prompter.continueButtonTitle = 'Go For It!';
     prompter.addParameter('Username: ', 'username')
     .addParameter('Password: ', 'password', 'secure')
     .addParameter('Email Address: ', 'email_address')
     .addParameter('Other: ', 'other_field')
     .addParameter('Genre: ', 'genre', 'popup', genres)
     .addParameter('Media Type: ', 'media_type', 'picklist', 'Media Types List')
     .show('Enter a Username and Password and Stuff', output);

    It turns out that it works if I comment out the declarations of variables used in the prompter.

    Can anybody shed light on this?

    April 10, 2021 at 12:44 PM #44119

    johnny_law
    Participant

    The reason I was playing around with the original prompter code is while using the async function prompter example that Daniel gave me which worked, as soon as I made a setFieldValue(x,y) in the call back funtion Tap Forms would crash. It would not if the script was run in the editor. Only if run directly.

    I was thinking it might have to do with the async nature of the call and the field level scripts. But I created a new Field that had no reference in field level scripts and tried to save to that field and again Tap Forms would crash if the script was directly run. On start up the field was not saved. But again if run from the editor it would save the info into the new field. Very Strange behavior.

    April 10, 2021 at 2:52 PM #44120

    Sam Moffatt
    Participant

    Don’t know why it works if you comment out the variables it works. Again I copied and pasted from the website and it worked fine for me so certainly weird. Though I generally try to put the variables at the top of the script personally, a force of habit from QBASIC many moons ago.

    Also odd that you get a crash with the async await there, hopefully Brendan gets the stack dump and can see what went wrong there. I’m paranoid about saving things (too many bad experiences with Word 95) so I frequently save things though on the mobile devices it’s a little harder.

Viewing 20 reply threads

You must be logged in to reply to this topic.