Tap Forms app icon half
Tap Forms Forum text image
Blue gradient background

Exchange tips and ideas with the Tap Forms community

Search Results for 'script'

Viewing 15 results - 1,771 through 1,785 (of 2,989 total)
  • Author
    Search Results
  • Sam Moffatt
    Participant

    I did a script to copy records from one form to another generically a while back as well, a little longer than Daniel’s script but also leverages a prompter to offer a target form to use.

    Daniel Leu
    Participant

    Hi Victor,

    When I run the script where the Enquiry form has more fields than the Contact form, then the script creates errors. In my case, the additional field is before some of the valid fields and this results in not all fields being copied…

    I have enhanced the script by adding a check to verify that the Contact form contains a field with the same name:

    function New_Client_Contact() {
    
    	// Define client form 
    	const clientForm = document.getFormNamed("Client Contact");
    	
    	// Create new record
    	let clientRecord = clientForm.addNewRecord();
    	
    	for (field of form.getFields()){
    		if (clientForm.getFieldNamed(field.name)){
    			let clientFieldId = clientForm.getFieldNamed(field.name).getId();
    			clientRecord.setFieldValue(clientFieldId, record.getFieldValue(field.getId()));
    		} else {
    			console.log("Waring: Field '" + field.name + "' not found in 'Client Contact' form");
    		}
    	} 
    	// Save
    	clientForm.saveAllChanges();
    }
    
    New_Client_Contact();

    Cheers, Daniel

    ---
    See https://lab.danielleu.com/tapformspro/ for scripts and tips&tricks

    Victor Warner
    Participant

    T.L. and Daniel,

    Thank you both for the scripts. I am very grateful.

    Daniel,

    I have query on your second script. Using the Form names based on the following:

    1. the Client Enquiry has more fields then the 3 in the example but the additional fields do not exist in the Client Contact form.
    2. when the second script is run all the fields are copied for a record into the Client Contact form but although the ones for First Name, Last Name and Description are copied across to the Client Contact form the rest of disregarded.

    There is no downside (data corruption etc)?

    #41560
    T.L. Ford
    Participant

    Thank you for the feedback, Sam! It’s never possible to proofread your own work and find all of the errors (I did try). I added a “next” link to each page.

    I wanted to add many more things (walk-throughs of all of the snippets, not just a couple, and some more useful examples). I ran out of time (time-sensitive projects queued) and I figured for 101, this bridges the gap between “I have never written a script in anything in my life… Help!” and “ok, I’m capable of figuring out code posted to the forums…”.

    I made some decisions to “keep things as simple as possible”. For example, console.log and JavaScript – a true beginner will not understand the nuances of the under-hood implementation of JavaScript/Objective C. If I explain it as OOC, it adds a ton of web tutorials that can help explain objects which is a useful concept for grasping how to use forms, records, fields, etc. At the point in their programming career where they have jumped to a compiled language, they’ll know enough to be able to appreciate the difference. As a programmer, it’s cringeworthy. As a teacher for the utter newbie, the concept works.

    I hope you don’t mind that I added your description for console.log and JavaScript as a footnote.

    “For Section 6, why did you pick the basic loop over the child records loop?” – Failure to remember that such a thing existed until after I’d already done it and too lazy to go back and change it. I did mention it afterwards.

    “As an aside third parameter comment” I liked Objective C data types. Oddball syntax but once you got used to it, it was nice enough. Swift data types (when I played with it) were pure [profanity deleted].

    “For Section 7, the .length property is generally cached these days by the runtime. Google and V8 drove that optimisation which meant everyone else (including Apple) picked it up.” I learn something new every day. :)

    I added your array / join to the downloaded zip and put a note about it on the page, because it’s definitely worth noting. I liked the additional reinforcement of string concatenation (true beginners struggle with it a bit), but array/join is more efficient. I’m a super-guru Microsoft Access VBA developer. Array.join() is a magnificent thing.

    This is the same reasoning behind letting the code do the full string concatenation and then whacking off the ending comma. It keeps the inside loop block as simple as possible to focus on the process of looping. A string can be logged and easily understood. An array is very fuzzy in the minds of utter newbies.

    “For the audio it sounds like fan noise” It’s definitely the computer fan – I even tried killing our air conditioning which blows just overhead and can add a hum (not very useful for the heat problem, but in this heat wave, I certainly didn’t leave it off long enough for the room temperature to change).

    I ran one of the audios through Adobe Audition (the one where I sound like I’m standing in an auditorium). I have Audacity, too, but didn’t try that. I was busy grumbling at my computer. I’ve done a lot of videos. Some setting has gotten mucked up and changed the pickup threshold. I’ll get it sorted out before I do another video (my current theory is iTunes’ no-stealy implementation + Discord voice chat + SnapZ screwing up the capture, and could also have been the detour through the accidental click on my EOS Utility/OBS – next up: how to abuse your computer 101). It likely needs a reboot and some preference tweaking, but I had too many things open to do a reboot just then.

    More “correct/efficient” Tap Forms walkthroughs would definitely be useful. I don’t feel savvy enough yet with Tap Forms to know the best ways. (example: why didn’t I use that Child records loop? Although I might make the lame excuse ‘so people could see how that basic loop can be edited’, which would be cool if that were the reasoning, not just my overlooking it.)

    Again, I really appreciate the feedback!

    #41558
    Sam Moffatt
    Participant

    Love the styling on the pages though I would have liked a more obvious “next” button to go to the next section. Look forward to seeing more expansion here though! Walk through guides for Tap Forms is something that I feel is missing but could be very useful. Perhaps you’ll end up writing “Tap Forms 5: The Missing Manual” at the end of it all.

    Minor bug on the functions page, you reference console_log not console.log. Additionally console.log will return to you the value of the property, for built-ins it’ll be a wrapper around native code though pure Javascript functions will return the implementation. Javascript is also generally referred to as a prototype based language and as such doesn’t have classes, just objects that you can extend upon (in a sense they’re all just dictionaries with some self referential sugar). It’s a slightly different approach than class based object orientated programming hierarchies.

    For Section 6, why did you pick the basic loop over the child records loop? As an aside third parameter comment is probably more correct than wrong because of the way Javascript treats falsey types. I wouldn’t be surprised if it’s not coerced to a boolean before being marshalled back to Objective-C.

    For Section 7, the .length property is generally cached these days by the runtime. Google and V8 drove that optimisation which meant everyone else (including Apple) picked it up.

    Instead of doing string concatenation, I’d use an array and join:

    let current_chores = [];
    ...
    current_chores.push(chores[index].getFieldValue(chore_id));
    ...
    console.log(current_chores.join(", "));
    

    A similar one solution would work for the name list as well which would make it easy to prefix or suffix titles, add middle names or more. Saves you having to deal with substring and let’s Javascript do the heavy lifting for you.

    An alternative trick is to check if the string has a length and append the join characters in the middle after the first iteration of the loop:

    if (current_chores.length) current_chores += ", ";
    current_chores += chores[index].getFieldValue(chore_id);

    For the audio it sounds like fan noise, try grabbing Audacity and using it’s noise reduction plugin on the audio to see if it can clean it up. Fan noise is the bane of my own recording existence.

    Looking forward to seeing what you tackle next though!

    Daniel Leu
    Participant

    Yes, you would use a form script for this and start it from the client inquiry form. If you use a custom layout, you can even put a button there to start this script!

    Following is a form script that creates a new record in the form named “Client Contact” and copies first name, last name and description fields. This script assumes that the field names are “First Name”, “Last Name”, and “Description”:

    // Define enquiry form ids
    const firstNameId = form.getFieldNamed("First Name").getId();
    const lastNameId = form.getFieldNamed("Last Name").getId();
    const descriptionId = form.getFieldNamed("Description").getId();
    
    console.log(record.getFieldValue(firstNameId));
    
    function New_Client_Contact() {
    
    	// Define client form and ids
    	const clientForm = document.getFormNamed("Client Contact");
    	const clientFirstNameId = clientForm.getFieldNamed("First Name").getId();
    	const clientLastNameId = clientForm.getFieldNamed("Last Name").getId();
    	const clientDescriptionId = clientForm.getFieldNamed("Description").getId();
    
    	// Create new record
    	let clientRecord = clientForm.addNewRecord();
    	
    	// Populate new record
    	clientRecord.setFieldValue(clientFirstNameId, record.getFieldValue(firstNameId));
    	clientRecord.setFieldValue(clientLastNameId, record.getFieldValue(lastNameId));
    	clientRecord.setFieldValue(clientDescriptionId, record.getFieldValue(descriptionId));
    	
    	
    	// Save
    	clientForm.saveAllChanges();
    }
    
    New_Client_Contact();

    The beauty of this script is that it doesn’t use hard coded field ids. But if a field name changes down the road, the script will not run anymore. That’s the disadvantage of not using hard coded field ids ¯\_(ツ)_/¯

    If you want to copy all fields from “Client Enquiry” to “Client Contact”, I have a shorter version of the script that just loops over the fields. This script assumes that the fields are named the same in both forms and have the same type (eg, text field):

    function New_Client_Contact() {
    
    	// Define client form 
    	const clientForm = document.getFormNamed("Client Contact");
    	
    	// Create new record
    	let clientRecord = clientForm.addNewRecord();
    	
    	// Loop over fields and copy their content
    	for (field of form.getFields()){
    		let clientFieldId = clientForm.getFieldNamed(field.name).getId();
    		clientRecord.setFieldValue(clientFieldId, record.getFieldValue(field.getId()));
    	}	
    	// Save
    	clientForm.saveAllChanges();
    }
    
    New_Client_Contact();

    Note: I personally would use one form and have a field “status” that identifies if this is just an enquiry or if it turned into a client.

    Cheers, Daniel

    ---
    See https://lab.danielleu.com/tapformspro/ for scripts and tips&tricks

    T.L. Ford
    Participant

    Here’s a code solution and how I did it. Ignore where I went and got the form id – didn’t need it. There’s no sound (me and my computer recording software are at war just now).

    You can make a menu shortcut to run the script if you want. That’s at the bottom under the script name.

    Basically, the script gets the values for the fields on the current record, and puts those values on a new record on the Client Contact form. Your field IDs will be different.

    – T

    Attachments:
    You must be logged in to view attached files.
    Victor Warner
    Participant

    T.L.

    Thank you for the reply. I do in fact want to do fact I described as the two forms will after creating the new record in the Client Contact form will no longer need to be in context with each other.

    The Client Enquiry form is there to capture details of a client enquiry, and if I am instructed I would like to then create a record in the Client Contact form without having to type some details again. But after that I will not be referring t the Client Enquiry form again.

    Also using scripting will help me to learn JavaScript.

    Any further help will be gratefully received…

    #41546
    T.L. Ford
    Participant

    I just finished assembling
    Tap Forms Javascript Scripting 101

    This beginner level tutorial:

    * Teaches you how to read the scripts.
    * Teaches you how to use the scripting interface.
    * Teaches you how to apply the documentation.
    * Teaches you how to write simple scripts.

    You do not need to have any experience programming or working with scripts.

    http://cattail.nu/tap_forms/tap_forms_scripting_101/index.html

    I wanted to answer some beginner scripting questions that I see in the forums and empower people to wield Tap Forms’ scripting power (it’s really cool!). I hope you find it helpful.

    Victor Warner
    Participant

    I have two forms (Client enquiry, Client Contact). In the example both have the same fields in each:

    First Name
    Last Name
    Description

    Would I would like to do:

    1. From a currently selected record in the Client Enquiry form;
    2. Create a new record in the Client Contact form;
    3. Put the values of First Name, Last Name and Description in the new record in the Client Contact form.

    Would I be creating a Form script rather than a field script?

    Would I be starting from the Client Enquiry form?

    Would be the code to do so?

    Any help would be gratefully received.

    #41544
    pierrot_rennes
    Participant

    Hi Sam,

    Really thank you very much for your help, your explanations and the script !!!
    thank you very much and respect for the time you spent on this

    I just integrated the new script and I made two or three tests quickly by modifying the properties of some fields as you explained to me
    It seems to work fine and in the way that suits me ;-))

    I will experiment and test at the field level
    And especially to learn the links of forms and controls ;-)

    I will also try to be inspired by your script code although the code is not my preference ;-))
    Very long practice of IT but rather on the hardware side, network and troubleshooting …

    Thanks again for your help
    Best

    #41536
    Sam Moffatt
    Participant

    With the link you can absolutely fill it in from the Magazines form, that makes complete sense because when you add from the Magazines form, it autolinks the Magazine to the article for you similar to how the Table field operates.

    The Articles form is just a more accessible version of the table field you created, I think under the hood Brendan modelled them the same way, it’s just that you don’t see the form as the field itself is the form. You could hide the Articles form if you wanted so you’d not see it in the forms list but would still be able to interact with it. I personally like having them all available but the option is there.

    We can automate a lot of things using the calculation fields to pull data from the parent record. Tap Forms can’t give you a table view that has fields from either two different forms or fields from the parent form and rows in a table field. That’s in part where that Articles form comes in because we can reference that from other forms (Keywords in this case) and since it is linked to the Magazine form, we can use calculation fields in the Articles form to automatically replicate values from the parent Magazine form. The other advantage is that Tap Forms’ Link to Form JOIN field works on the form making it a little easier.

    If you only want to link to the magazine plus magazine month and don’t need the article name or page details (essentially anything in your articles table or the articles form) in your keyword form, then you could change the Articles form (and link) back into just a simple table. I might have misunderstood along the way but I thought it was useful to see the article and page details for the keyword as well. That’s what a lot of this is predicated on is pulling all of those fields together into the keyword to make a table.

    Looking at your second screenshot, if the Magazines link isn’t useful then you can safely remove it and for the articles link in your second screenshot if you click on the X button on the far right you can hide fields and reorder them (this also works in the multicolumn list view as well). Getting magazine month and number should be a calculation field that populates the value from the parent magazine form, this is just a matter of setting the fields up and making sure they have the right type (date for the month field and number for the number field [number should be the default]). If the calculation field is misbehaving, jump to the Articles form and click on the refresh icon on the bottom of the list view and it should recalculate the fields to update to the right value.

    The challenge with automatically creating a keyword if one doesn’t exist is that we need to scan the keywords form to find what keywords exist and do an insert if one doesn’t exist. If I was using something like MySQL, it has functionality that is optimised to make this mostly cheap through it’s indexing system but Tap Forms isn’t built with a columnar index structure but is a document store. That means we need to build the index ourselves. Doing this each time you edit the keywords field is probably a little intensive and would slow Tap Forms down as your database scaled in keywords. I’m also going to make an assumption that you’re going to hit a threshold where adding a new keyword is a rare event rather than a common one, as it will be today. Given both of those, I went to create a form script that handles it. You could also modify it to be a script field (might even work as is) but again that would be a little disruptive to editing that might not be appreciated.

    Here is a quick little form script that runs on the currently selected magazine record, scans the linked articles and checks the keyword table to see if it exists and creates a new keyword record if it doesn’t exist. It’s actually a slightly modified version of the earlier script, just without the link creation steps:

    function Update_Keywords() {
    	// This is the other form that has our keywords in it.
    	let keywordForm = document.getFormNamed('Keywords');
    	
    	// This is the field ID in the "keywords" form for the link to field to Magazines.
    	let magazines_id = 'fld-b4724a28d4094b3faa9910f18374588f';
    
    	// This is the field ID in the "keywords" form for the keyword field.
    	let keywords_keyword_id = 'fld-ebaf7ffa3d484834bdcc34d3ffb9c5f2';
    	
    	// This is the field ID in the "magazine" form for the keyword field in the articles table.
    	let keyword_id = 'fld-a75febca3ee54d2d9d77b8c176ac08db';
    
    	// Articles link field ID
    	let articles_link_id = 'fld-9af3b672710949d8a96591e23ba5466b';
    
    	// This is to store a map of keyword to keyword record.
    	let kwRecords = {};
    
    	// Build the map of keyword to keyword record (cache if you will).
    	console.log("Finding keyword records...");
    	for (let keywordRecord of keywordForm.getRecords())
    	{
    		console.log("Adding keyword: " + keywordRecord.getFieldValue(keywords_keyword_id));
    		kwRecords[keywordRecord.getFieldValue(keywords_keyword_id)] = keywordRecord;
    	}
    	console.log("Completed finding keyword records.");
    
    	// Iterate over every record in this form...
    	for (let sourceRecord of record.getFieldValue(articles_link_id))
    	{
    		// Get the value of the keyword field...
    		let keyword = sourceRecord.getFieldValue(keyword_id);
    			
    		// Skip it if it is empty...
    		if (!keyword)
    		{
    			continue;
    		}
    
    		// Check if a keyword record exists for it...
    		if (!kwRecords[keyword])
    		{
    			// Create keyword record if it doesn't exist...
    			console.log('Creating keyword record');
    			kwRecords[keyword] = keywordForm.addNewRecord();
    			kwRecords[keyword].setFieldValue(keywords_keyword_id, keyword);
    		}	
    		
    		// Log the keyword we processed, we're done!
    		console.log(keyword);
    	}
    	
    	// Save the changes.
    	form.saveAllChanges();
    }
    
    Update_Keywords();
    #41535
    Sam Moffatt
    Participant

    The Script Folder Access isn’t useful for putting scripts in but is another way of getting to the filesystem from outside of the App Store sandbox/container to import content. The sandbox limits your ability to arbitrarily read from the filesystem and this is a way of flagging a directory that can be accessed. I’m going to do an update to my receipt import process that uses it to import the images and blog about that when I get a chance because it’s a neat new feature. I personally wouldn’t use it to share scripts, the form.runScriptNamed makes more sense because it will be available on all locations for your document.

    The notes field is an implementation of UILabel/UITextView which is backed by an NSAttributedString that mostly has the capabilities of what you’d think of RTF (which was popular when it was originally created). It’s not a heavily featured control in many respects.

    Personally I use web links to spin up a new browser instance instead of embedding inside the app directly.

    #41526
    Ron Statz
    Participant

    must be an easier way without getting into scripts. In a custom form, all that is required is to put the text on the form screen.

    #41521
    Sam Moffatt
    Participant

    It is in the Articles table (link) that I must enter, isn’t it?
    What is the Article table for (Table0 in the form?

    The Articles (Table) (typo with the closing bracket, missed the shift key) was there for reference, probably should have deleted it. Moving forward you’d want to use the Articles (Link) because it enables a little more precise referencing of the individual records.

    When I run the script, the new records are not added in the Keywords form (only in the Articles form)
    Did I do something stupid or change something without realizing it?

    The script as written was targeted for the Articles (Table) field, if you’re using the Articles (Link) then all you need to do is create a new record in the Keywords with the value of the keyword that you’ve added then Tap Forms will automatically link everything together for you.

    For the Magazine Month field (calculation type), I cannot display it in a date format type MMMM YYYY

    Ok, for the Magazine Month field in the Articles form, go into the calculation settings and set the Result Type option on the left hand side under the field list to Date. That will tell Tap Forms to treat it like a date value rather than a text or number value. The default result type for calculation fields are numbers and the default result type for script fields are text.

    When it’s set to Date then you can use the other field settings to control how the date field displays.

Viewing 15 results - 1,771 through 1,785 (of 2,989 total)