Alternative to global variables - google-apps-script

Hi I am doing a simple script where I want to track what step I am up to and use the result from a button click handler.
1)I cannot pass the variable as it is an event
2)Cannot use global variables as they seem to be constants only once set
Is there any way to set and object or variable multiple times and access the current value from within a handler function?
Found several examples suggesting a hidden widget, as well as that being a poor solution I also struggled to retrieve the value once set. IE it had a .setValue but no .getValue
Help please this is not a difficult thing in any other language I have tried but new to GAS
Cheers

There are more options - one, as you mentioned is to use a hidden widget. Although there is no .getValue(), it can be accessed through e.parameter within the click handler.
Two, for small amounts of data, you can use ScriptProperties / UserProperties and CacheService
Third, you can use the script DB or a spreadsheet if you are dealing with large amounts of data.
Having said all this, it would be better if you can post some code of what you're trying to achieve. Many times, code speaks louder than words.

Private Cache is intended for this type of thing https://developers.google.com/apps-script/reference/cache/

Related

SolidJS: "computations created outside a `createRoot` or `render` will never be disposed" messages in the console log

When working on a SolidJS project you might start seeing the following warning message in your JS console:
computations created outside a `createRoot` or `render` will never be disposed
There are some information available on this in SolidJS' Github repository issues. But after reading them I was still not quite sure what this was all about and whether my code was really doing something wrong.
I managed to track down where it came from and find a fix for it based on the documentation. So I'm providing the explanation and the solution for those Googling this warning message.
In essence this is a warning about a possibility of a memory leak due to a reactive computation being created without the proper context which would dispose of it when no longer needed.
A proper context is created a couple of different ways. Here are the ones I know about:
By using the render function.
By using the createRoot function. Under the hood render uses this.
By using the createContext function.
The first is by far the most common way, because each app has at least one render function call to get the whole show started.
So what makes the code go "out of context"?
Probably the most common way is via async calls. The context creation with its dependency tree happens only when the synchronous portion of the code finishes running. This includes all the export default function in your modules and the main app function.
But code that runs at a later time because of a setTimeout or by being in an async function will be outside of this context and any reactive computations created will not be tracked and might stick around without being garbage collected.
An example
Let's say you have a data input screen and have a Save button on it that makes an API call to your server to save the data. And you want to provide a feedback to the user whether the operation succeeded or not, with a nice HTML formatted message.
[msg,setMsg] = createSignal(<></>)
async function saveForm(){
...
setMsg(<p>Saving your data.<i>Please stand by...</i></p>)
const result=await callApi('updateUser',formData)
if(result.ok){
setMsg(<p>Your changes were <b>successfully</b> saved!</p> )
} else {
setMsg(<p>There was a problem saving your data! <br>Error: </p><pre>{result.error}</pre> )
}
}
...
<div>
...
<button onClick={saveForm} >Save</button>
{msg()}
</div>
This will produce the above mentioned warning when the API call returns an error, but not the other times. Why?
The reason for this is that SolidJS considers the code inserts inside JSX to be reactive, ie: need to be watched and re-evaluated. So inserting the error message from the API call creates a reactive computation.
The solution
I found the solution at the very end of the SolidJS doc. It's a special JSX modifier: /*#once*/
It can be used at the beginning of a curly brace expression and it tells the SolidJS compiler to explicitly not to make this a reactive expression. In other words: it will evaluated once and only once when the DOM nodes are created from the JSX.
In the above example here's how to use it:
setMsg(<p>There was a problem saving your data! <br>Error: </p><pre>{/*#once*/ result.error}</pre> )
After this there will be no more warning messages :)
In my case, I had an input and when that input changed I re-created an SVG drawing. Because the SVG creation was an expensive operation, I added a debounce in the createEffect function which ran when the input changed. debounce is a technique to defer the processing until the input stops changing for at least X amount of time. It involved running the SVG generation code inside the setTimeout function, thus being outside of the main context. Using the /*#once*/ modifier everywhere where I inserted an expression in the generated JSX has fixed the problem.

Is it possible to change the title property of an object via a derived value from an edit form in Foundry?

I created an object that is backed by a Foundry Form and I would like to provide a user to change the properties of that object. I linked the form to the object and created a title property that is a hidden/ derived value in the object creation form. A user can edit property a and property b and the title of the object will be ab.
When the user updates the object in the edit form the title does not update. Is there a configuration I need to change?
Yes, this is possible. There's actually two ways to achieve this, I'll list them in order of my preference:
Using an action
The modern way of achieving this is to use an action. Actions allow you to flexibly "intercept" events like writes from users and do extra actions (hence the name) or prevent things from happening. They are a fairly new feature in foundry.
The basic concept is that you write a little piece of code (a function on an object) that gets executed when the object is modified. The function can then modify the object further or prevent the modification.
This is very flexible, because it will allow you to automatically update the title of the object regardless of how and when the object was edited. You can also apply more complex logic to derive the title from e.g. multiple properties with fallbacks, or modify a property in a certain way before you put it into the title, et cetera.
The drawback is that this requires you to write some code.
On your stack, if you navigate to https://www.palantir.com/docs/foundry/functions/use-functions/#actions you will find an introduction on how to get started with actions. The example solves the exact use-case you're asking for.
Using form templates
Another approach that's simpler and does not require writing any code, but is much less flexible, is to use a template in the form. You can create a template form widget that's invisible, and is automatically populated by values from other form fields.
The advantage is that this is very easy and quick to set up, but the disadvantage is that it will only apply when the object is edited through the form, and you can really only do concatenation, not much else.
It sounds like this is what you attempted to do, and I believe this should work. If it doesn't, I would check the following things:
make the template visible to see that it gets filled out like you expect it to
make sure the template is set to store its response into the right property on the object
make sure the user is using the form to edit the object, not some other way (like editing the property directly in hubble)

OleDbDataAdapter.Fill doesn't work when checkpoints are enabled

We faced a weird issue this week related to "OleDbDataAdapter.Fill" method in a script task. We are storing a query result in an Object variable and this data is used inside a script task. When checkpoints are enabled, we are not able to read the object variable using OleDbDataAdapter. When checkpoint is disabled - the code works fine.
Any workarounds for this issue ?
Regards,
Kumar
One cannot read variables from a blob object, which is what you would use to fill the OleDbDataAdapter using a debugger. You can however try to look through the results of the datatable to which you assign the value once that is initiated in the loop.
You can check this link that gives a very good breakdown of how to loop through object - https://www.timmitchell.net/post/2015/04/20/using-the-ssis-object-variable-as-a-data-flow-source/
In the script code that is pasted, you can put the debugger across foreach loop and then iterate and see through the results. This can be done

Get ramp attribute in compute()

I am basically making a ramp shader and trying to find the proper way to get values from a ramp attribute in the compute() function for a node.
I know it can be done with
MObject oThis = thisMObject();
MRampAttribute rampAttribute(oThis, aRamp); // aRamp is our ramp MObject.
but is it safe to do this in compute?
The Maya documentation mentions in a few places that, in compute, we should only use attributes in the MDataBlock to get input data, but I can't find a way to get a ramp attribute from the MDataBlock. I couldn't find any official code samples using MRampAttribute in compute() either.
Its fine to do this. I don't think you can access MRampAttribute from the data block. I have some plugins nodes that use it exactly as you wrote and I've not noticed any problem.
It's not the only occasion where you need to use the MObject to get a plug in compute() either.

Where in the Google source code is window.document.all function defined?

Any one know where the function window.document.all is defined? Tried searches but nothing coming up.
Many thanks
Edit: note I am aware that thus deprecated and documentgetelementbyid should be used. still need to know what is executed when this function is run.
It has nothing to do with Google V8. It is a legacy property of the document object. It stores an array of all elements in the document, indexed by ID.
You should use document.getElementById() instead.
If you are asking this question then the source code will probably not be useful to you in the first place. But here you go:
https://github.com/WebKit/webkit/blob/5b7f307f78ff665c0102bd008d2a47b9b2f8e5b5/Source/WebCore/dom/Document.cpp#L4405