Forum Documentation Showcase Pricing Learn more

[Plugins for Beginners]: Accessing Input Fields in Plugin Action Javascript Code


#1

Hey everyone…

I’m not a professional programmer, but I can put together the basics in most languages given a few hours to remind myself of the syntax… which may make me quite a typical Bubble user. So I decided to write a plugin with a server action using some basic javascript code, thinking it would be quite easy. Boy have I just been round the houses on the most basic issue of how to read input fields. Before I forget the pain and the details, I want to document it here for all those who follow in my footsteps!

First, before you go anywhere on plugins, I recommend doing the wonderful Plugin Development course from the @copilot guys. Click here for the details.

Text Inputs - The Easy Bit
So text inputs are pretty easy. Define them like this:

And then in your code you can get the value you specified using the syntax:
properties.text_in

Text Output - For Action Running on Server
Define your “result” outputs like this:

And then in your javascript, write to the output with the line:

return {"text_out": myText};

where myText a text variable you have created within your code. Just don’t forget the quotes around “text_out” as I did for a short while.

Text Output - For an Element Action
In this case, you define an “Exposed State” of the element in the same style as shown above. The code to write to these outputs is:

instance.publishState("text_out", myText);

Custom Type Input - Not at All Obvious!
Wow, this part took me hours and hours to work out. I just couldn’t find one place to give me the answer, things I read were talking in slightly too technical javascript gobbledegook, and sometimes forum post I read were not quite accurate.

But YEAY, I have just worked it out. I’m so happy…

So this is for an input which is of absolutely any type you have defined yourself… so maybe a type called “Contact”, or “Event”, or “Invoice” for example.

The first thing is you need to define your input to be of type “any thing” like this:

Now the next part depends on which kind of action you are defining…

For an Action which runs on the Server…
Then you have to realise that when you try to access this input (properties.anything), it will probably be empty (null in javascript parlance), even though you specified a value in your workflow. That is because, as a user defined thing rather than just a piece of text, it needs getting from the database. So first you need the line:

properties.anything.get();

( For an Action which is part of an Element… you don’t need to do this - in fact the above line will throw an error.)

And to save yourself typing the “properties.” bit the whole time, it can be useful to define a variable for this:

var anything = properties.anything;

which will send the plugin off to the database to go and fetch it. There is a bit of an issue around the timing of that process and whether your function will run more than once, which you can read about in the manual - click here for all the details.

Now it exists in your code… but how on earth do you access its field values?

Well firstly, you need to run a very special function to see what the fields have been renamed to now they are in javascript land. Execute this line of code and send the result to a text output or the console:

x = anything.listProperties() + "\n";

(If you don’t have the + “\n” part concatenated, you may need to convert the type to a string, so with the line:
x = toString(anything.listProperties());

This gives you a big comma separated list. It is easier to read with each field name on a new line, which with a bit of javascript digging around, can be done like this:

t = x.replace(/,/g,'\n');

which globally replaces the commas with a new line. Then you end up with a usable list of the field names, which will look something like:

first_name_text
deleted_boolean
number_number
start_date3_date

(note that the names may not match your Bubble field names if you have been renaming some of your Type’s field names in Bubble)

And then… you can access the values of the individual fields with the syntax:

t = anything.get("first_name_text") + "\n";

(assuming you defined the variable
var anything = properties.anything;
as shown above).

Wow, what a journey… and one that I hope will save lots of time for many enthusiastic Bubblers in the future.

Good luck! :grinning:

But wait… there is more…

As I start to apply this, here are more of my learnings…

Specifying the Thing on the Action in Your Workflow
So when you call up your nice new server action in a workflow, you have to be really careful. What is the difference between these two?

Plugins%20(4) Plugins%20(5)

Yes, it is the word “value”. For some unknown reason, when calling up a plugin server action, Bubble lets you specify the name of an input, as well as the name of the input’s value. In all other areas of Bubble, you can’t do this! Beware, as without the important “value” part, you will not pass a value on to your plugin and the get() function will always fail!

Working with Lists of type "any thing"
With a list of type “any thing”, you first need to get the whole list from the database… and it is best to store this in a variable to make access easier later on. So if your input field is called “anythinglist”, then you need the line:

var anythinglist = properties.anythinglist.get(0, properties.anythinglist.length());

(note two things - the () after length, and the fact that we use length() rather than length()-1 )

Then to access the field of a specific item within the list, you can use the standard javascript array syntax [i] on anythinglist, followed by the .get() function:

t = anythinglist[i].get("first_name_text") + "\n";

(and this coding is the same whether you are creating an Action or an Element Action)

Protecting Against Getting Something That Isn’t Specified
You also need to be careful to test in your code that there actually is a value on the input before you do the get function. Do this by testing that the input field exists in the first place:

if (properties.anything) {properties.anything.get();}

Performance of Server Actions
At the time of writing (10 Feb 2019), there appears to be a big performance hit in writing a server based action… I just wrote one that takes 40 seconds to run on the server, and literally milliseconds to run as an element action running locally on the client. Bubble are taking a look at this at the moment.


Plugin Server Side Action: Cannot Access Input Field of Type "any thing"
[Plugins for Beginners] - Tips I Have Written
Accessing Custom Type's Values in Javascript
[Plugins for Beginners]
#2

Wow, thanks for sharing, @antony, and for your dogged persistence in working out the details! :+1:

Would you mind sharing a screenshot of how your custom “thing“ is defined in the database? I’m thinking that might shed some light on how field names are transformed in JavaScript code.


#3

Hey @shot, it’s a pleasure.

I just edited the post for clarity to answer your question. I added the line:

So this is for an input which is of absolutely any type you have defined yourself… so maybe a type called “Contact”, or “Event”, or “Invoice” for example.

So yes, basically any thing and every thing you have defined to be of a custom type!

I’m realising there is a pattern to the naming structure, but it isn’t reliable. That is because the name is based on the original name you gave the field of your type. If like me you have changed the names during your development, the javascript name is a closer relation to the original name than its current one!

I hope that makes sense,
Best wishes,
Antony.


#4

Hello! Something I can not. I do everything as it is written, but after the line properties.anything.get (); - I get the error: Error: Invalid from: undefined. Something is wrong with the line: properties.anything.get ();


#5

Hey @vasanbo, thanks for your input… yes, I have just realised I missed out a line in my explanation. I just edited the post to fix it.

So from what you read, you need to add the following line for my code utilising the get() function to work:

var anything = properties.anything;

Or, you could have put on your get() line:

t = properties.anything.get("first_name_text") + "\n";

Sorry about that!