Using .get('field_name') on a Bubble Object not returning data in time

What I’m trying to do is -

First retrieve a list of “things” via properties.list_of_bubble_things.get(0, properties.list_of_bubble_things.length())

Then, I’m attempting to do a .forEach on every single one of those objects, to retrieve a data field for every single bubble object.

Example code -

var things = properties.list_of_bubble_things.get(0, properties.list_of_bubble_things.length());

things.forEach(element, index){
var field = element.get('field_name');
//more code that uses the above field variable
});

Issue is, the field variable is always equal to null, as the function hasn’t loaded that data yet.

Also, to specify, this field I’m attempting to use is a date range, and isn’t a link to another data type.

I’m assuming this can be fixed using an async function, but i’m not too familiar with how to do that, especially since the async function must be called for each bubble object, then rest must be executed when all values are loaded.

Also, just to note, this is a server side action. Everything works perfect client side.

Any help/ideas is appreciated. Thank you!

This is what I always use

//This code get the list as an object which you can then iterate over
let objToFetch =  properties.list.get( 0, properties.list.length());

//Use this code if you need to examine the object length 
console.log('objToFetch',objToFetch.length);

//Get and add variables to plugin
objToFetch.forEach(e => {
    let n = e.get(properties.variable_names);
    let v = e.get(properties.variable_values);
    //use this code to examine the results console.log('Variable Added','Vartiable Name:',n,'Variable Value:',v);
});
1 Like

This is normally fine for me, per @AliFarahat 's method.

To me it looks as though your use of forEach has an error in it.
The syntax should be:
*your-array*.forEach((item, index) => {*your function code*});

I think you are missing an ( after forEach and an arrow function => after the parameters… to it would read: things.forEach((element, index) => { *** })

You might have already worked this out after seeing the example above.

1 Like

Thanks for the replies @exception-rambler @AliFarahat . I don’t think that is the issue here, as I have it running with my syntax on a client side element.

*your-array*.forEach((item, index) => {*your function code*}); is the shorthand version of my forEach function.

I’m working on a server side action since I need to be able to run this plugin on the backend. Also the issue doesn’t seem to be on loading the data at this part

var things = properties.list_of_bubble_things.get(0, properties.list_of_bubble_things.length());

It seems to be when trying to access a field from here like so.

var thing = properties.list_of_bubble_things.get(0, properties.list_of_bubble_things.length())[x].get('fieldname'); as this will return null as it hasn’t been loaded by the server yet.

According to Bubble, this should be something that is handled automatically. https://manual.bubble.io/account-and-marketplace/building-plugins/loading-data

You can also go look at the List Popper SSA in my free List Popper and Friends plugin for an example of how you fetch a List.

Thanks for the reply Keith, however I don’t think that’s it either.

Posting whole code here that works as a client side element. Problem is it won’t load server side.

It’s a simple plugin. We’re reading a date range field, converting into a luxon interval, then finding overlapping dates.

var needs = [];
var availabilities = [];
var needsObjs = [];
var availabilitiesObjs = [];
var overlappingNeeds = [];
var overlappingAvails = [];    
    
if(properties.vetprof_availabilities_data){
    availabilities = properties.vetprof_availabilities_data.get(0, properties.vetprof_availabilities_data.length());    
}

if(properties.vetprac_needs_data){
    needs = properties.vetprac_needs_data.get(0,properties.vetprac_needs_data.length());
}
        
needs.forEach(function(element, index){
    var thisRange = element.get('start_end_range_date_range');
    var luxonRange = luxon.Interval.fromDateTimes(thisRange[0], thisRange[1]);
    var thisID = element.get('_id');
    var newObj = {};
    newObj.range = thisRange;
    newObj.luxonRange = luxonRange;
    newObj.id = thisID;
	newObj.bubbleObj = element;
    needsObjs.push(newObj);    
});

availabilities.forEach(function(element, index){
    var thisRange = element.get('start_end_range_date_range');
    var luxonRange = luxon.Interval.fromDateTimes(thisRange[0], thisRange[1]);
    var thisID = element.get('_id');
    var newObj = {};
    newObj.range = thisRange;
    newObj.luxonRange = luxonRange;
    newObj.id = thisID;
    newObj.bubbleObj = element;
    availabilitiesObjs.push(newObj);
});

needsObjs.forEach(function(element, index){
	availabilitiesObjs.forEach(function(element2, index2){
    	if(element.luxonRange.overlaps(element2.luxonRange)){            
            if(!overlappingNeeds.includes(element)){
            	overlappingNeeds.push(element);    
            }
			if(!overlappingAvails.includes(element2)){
            	overlappingAvails.push(element2);    
            }
        }	    
    });    
});    

var needsBubbleObjs = overlappingNeeds.map(a => a.bubbleObj);
var availsBubbleObjs = overlappingAvails.map(a => a.bubbleObj);
    
instance.publishState('needs_that_overlap_with_availabilities', needsBubbleObjs);
instance.publishState('availabilities_that_overlap_with_needs', availsBubbleObjs);

Problem is here
var thisRange = element.get('start_end_range_date_range');

Plugin is only specifically for one app, so the field name is static. Used .listProperties() to get a list of field names.

Note that version 1 of the SSA API is fucked vis-a-vis how List.length() works. Use latest version of the API for compatibility with client-side code.

(I’ve not read your code carefully, just pointing out the most common issues with List-related Bubble plugins.)

Best regards,
Keith

1 Like

The reason there’s a version 2 is that I reported this particular bug.

Thanks for the ideas. I’m throwing in the towel on this one, I’ll be able to get away just using the client side element.

However, I will place a bounty on it. $150 dollars to the first person that can get my plugin running successfully as a sever side action.

Here’s the working client side element set up.

Vetprof Availabilites & Vetprac Needs both have a DB field called “Start-End Range” which I am accessing through .get(‘start_end_range_date_range’)

Html Headers -
<script src="https://cdnjs.cloudflare.com/ajax/libs/luxon/2.1.1/luxon.min.js" integrity="sha512-R3qVfQx4LUWixeZgtptH0NDb+/FB8qVflpPQUKzDQlz1zKE3BiN4wG3aBUwzabgMo/45MXHucjcC2/BWBxMJwQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

Working client side element code

function(instance, properties, context) {

var needs = [];
var availabilities = [];
var needsObjs = [];
var availabilitiesObjs = [];
var overlappingNeeds = [];
var overlappingAvails = [];    
    
if(properties.vetprof_availabilities_data){
    availabilities = properties.vetprof_availabilities_data.get(0, properties.vetprof_availabilities_data.length());    
}

if(properties.vetprac_needs_data){
    needs = properties.vetprac_needs_data.get(0,properties.vetprac_needs_data.length());
}
        
needs.forEach(function(element, index){
    var thisRange = element.get('start_end_range_date_range');
    var luxonRange = luxon.Interval.fromDateTimes(thisRange[0], thisRange[1]);
    var thisID = element.get('_id');
    var newObj = {};
    newObj.range = thisRange;
    newObj.luxonRange = luxonRange;
    newObj.id = thisID;
	newObj.bubbleObj = element;
    needsObjs.push(newObj);    
});

availabilities.forEach(function(element, index){
    var thisRange = element.get('start_end_range_date_range');
    var luxonRange = luxon.Interval.fromDateTimes(thisRange[0], thisRange[1]);
    var thisID = element.get('_id');
    var newObj = {};
    newObj.range = thisRange;
    newObj.luxonRange = luxonRange;
    newObj.id = thisID;
    newObj.bubbleObj = element;
    availabilitiesObjs.push(newObj);
});

needsObjs.forEach(function(element, index){
	availabilitiesObjs.forEach(function(element2, index2){
    	if(element.luxonRange.overlaps(element2.luxonRange)){            
            if(!overlappingNeeds.includes(element)){
            	overlappingNeeds.push(element);    
            }
			if(!overlappingAvails.includes(element2)){
            	overlappingAvails.push(element2);    
            }
        }	    
    });    
});    

var needsBubbleObjs = overlappingNeeds.map(a => a.bubbleObj);
var availsBubbleObjs = overlappingAvails.map(a => a.bubbleObj);
    
instance.publishState('needs_that_overlap_with_availabilities', needsBubbleObjs);
instance.publishState('availabilities_that_overlap_with_needs', availsBubbleObjs);
    
    
}

The bounty has been claimed! Posting solution here for anyone that might get stuck with the same issue as I did.

The solution in my case, was to call an additional .get() function on the date range field.

Before I was trying
var thisRange = element.get('start_end_range_date_range');

What works is
var thisRange = element.get('start_end_range_date_range').get(0,2) which returns an array of two dates (start and end)

Thank you to @juicebox for figuring out the solution!

2 Likes