A simple list of anything field returns "properties.list.length is not a funtion"

Hi everyone,

I am trying to build another plugin & there seems to be a bug from my point of view.

My setup (I am in testing mode) includes only one list field of type any thing:

When I try to get the length of the list in the update function with the following:
let len = properties.list.length();

It returns the error below:
TypeError: properties.list.length is not a function

Just a few days ago this worked perfectly fine.

It would be great if someone could verify this behavior on their end (maybe this is just happening for me)?

I am happy to provide more details.

Thank you for your answers.

Did you try it without the parentheses? It might be just what it says - i.e. that “length” is a property and not a method.

Very sorry you’re having this issue! Can you file a bug report for this case? We’ll need to look at your application, and then the success team will be able to assist you.

Thanks!

Thanks a lot @emmanuel, will file a bug report.

Yeah thought the same first, that I left out the “()”, but that was unfortunately not that easy. :stuck_out_tongue:

There’s no bug here. You’re just indiscriminately calling .length(), forgetting that, if there’s no expression provided for your field called list, the value there will be null instead of a List object.

Now, in your screenshot, you’ve got list set up so it’s not optional. All that does is activates the Issue Checker to warn the Bubble programmer that this field should have an expression in it.

However, that does not relieve you (the plugin author) of the responsibility to check that there is actually a value in properties.list before trying to access the get() or length() functions on that List object.

If the user leaves the field empty, the value you get for properties.list will be null, not a List object and when you do properties.list.length() there is of course no function there (null.length() is not a thing).

So, typically what we do when we are resolving our properties — particularly if we are need to use these values in other places all around your plugin code — is move them from the properties object to some other variable OR (and this is way better) put them on the instance object using instance.data.

So for your field you named list:

var the_list
the_list = properties.list ? properties.list.get(0, properties.list.length()) : []

:point_up: that is, if properties.list is non-null, get the list, otherwise return an empty array.

Bonus beats:

If you’re gonna be doing a lot of stuff with lists, it’s a good idea to just make a list getting function to make this easier.

Like, you might set one up like:

function getList(List) {
    var returnList = []
    if (!List.hasOwnProperty('get')) return returnList
    if (!List || List.length() < 1) return returnList 
    // this next step would just return us our array of items
    returnList = List.get(0, List.length())
    // however we might want to just get some field or whatever... you could add a "field" argument to this function or do other fancy stuff instead, e.g.,
    // returnList = List.get(0, List.length()).map(item => item.get('_id'))
    return returnList
} // end getList

And further, what I like to do with functions like these is put them in instance.data so we can access them anywhere in our plugin (define them in initialize!):

instance.data.funcGetList = function getList(List) {
        var returnList = []
        if (!List.hasOwnProperty('get')) return returnList
        if (!List || List.length() < 1) return returnList 
        // this next step would just return us our array of items
        returnList = List.get(0, List.length())
        // however we might want to just get some field or whatever... you could add a "field" argument to this function or do other fancy stuff instead, e.g.,
        // returnList = List.get(0, List.length()).map(item => item.get('_id'))
        return returnList
    } // end getList

And then in your update function:

instance.data.the_list = properties.list ? instance.data.funcGetList(properties.list) : []

1 Like

Hi @keith,

really lovely answer right there. Thank you very much for taking the time here.

I really appreciate it, however, just for debugging I commented out everything around what was there and just tried to get the list length to get to the bottom of the logged error.

I did check before whether the list was empty but that was unfortunately not the case either. Could have provided that info before, sorry for that.

Thank you again very much for that long and interesting read.

For those interested something similar has happened before and was fixed:

Hmmm. I guess if there is a bug here, it must be related to the type of expression being used in you “anything” field.

I have fields of “anything list” in List Shifter and use them regularly.

Used the anything list field (to send a list of texts) to the plugin yesterday for an example I created and worked fine.

Are you really sure?

Log the heck out of it. Like:

console.log(‘props.list is:’, properties.list, ‘type of props.list is:’ typeOf(properties.list))

Really, what is properties.list showing up as?

Don’t just copy and paste my code above, of course, I’m on my phone and surely the quotes are jacked up.

Hi again,

without any spaces this returns the following:
props.list is:type of props.list is:object

Just logging the object returns an object with the right number of things in it but each thing is null.

I think it is really similar to the issue alluded to in the forum post.

Thank you again!

It has no keys? Is it a null?

What’s the expression you’re sending to the field?

Yes it has keys. One for each instance and the value of each key:value pair is a null.

The expression is very simple: Current User's Things:filtered,

even without filtering and just a Do a search for Things it returns a list of the right size (= count of key:value pairs is correct).

I think this is a bug, I have tried a lot more in addition to looking into whether privacy rules are blocking or another plugin can give a proper return value for the length which both did not yield the desired result.

Have you taken a look if you create a new plugin with the identical setup, in order to potentially replicate the issue?

Thank you, @keith !

Gotcha. Yeah, I can I give it a shot to see if it can be replicated. (In case I should be able to do that, what’s your bug report number?)

Cheers,
K

Thanks that’s Bug report #10235.

Interestingly without changing anything, now I can get the list length but not any fields whose values are still null.

Cheers,
J

I think you’re still confused. Once you have a List, you don’t know anything about the items in the List.

A List is an object with 2 functions on it “get” and “length”.

Looking at my getList function I posted earlier, what does it return?

It returns an array of… something. But what somethings are these? Well:

  • If the List is a list of primitive Bubble data types, we will have a ready-to-use array of that type.
  • If the List is a list of Things, we will have an array of Things.
  • Edit: We might also have a list of object that are, themselves, MORE LISTS!

A Thing (a custom data type from the app) is not useful to us yet. A Thing is (yet another) object that has 2 functions on it, “listProperties” and “get”. The listProperties function returns to us a list of field names. Any of those individual field names can be passed to the Thing’s “get” function to retrieve the value stored in that field.

Keep in mind that the value stored in that field may be:

  • Another List ( :exploding_head: :exploding_head:)
  • Another Thing ( :exploding_head:)
  • A primitive data data value (e.g., a string, number, date, date range [array(2) of dates], numeric range [array(2) of numbers], etc.)

OK, so how do we tell these items apart?

Well, in order of specificity, this is how you can check the items in the list for their “type” in this context. Look at one of the items:

  • A Thing will have property called “listProperties”. (i.e., item.hasOwnProperty(‘listProperties’) will be true… we use this property as the first check because both Lists and Things have a “get” property, right?)
  • If the object doesn’t have the “listProperties” property, it may be a List or a primitive data value. A List will have the property called “get”, while a primitive value will (of course) not. (i.e., having failed the check above, item.hasOwnProperty(‘get’) will be true.)
  • If neither of the above checks passes, the item is of a primitive data type and the item is ready-to-use.

Alright @keith, I am not confused here.

I have tried it with get(“field_name”) of course.

The value stored is just a simple text. Alpha3country code in this specific instance.

Were you able to replicate this behavior in a new plugin?

Thanks.

If it will always be of that type, just use the usual technique: Make your input field of type text and check is a list.

There’s a reason for doing that, by the way…

If you don’t know the List’s type, you’ll never be able to export it from the plugin.

You’ll see in when I post my example plugin…

OK, so… I cannot reproduce your “bug”. Again, your problem is that you do not understand what an input of type “anything list” would be used for… nor how you would handle it.

But, I made a plugin that attempts to explain it to you:

This plugin is here: Go inspect it. https://bubble.io/plugin/anything-list-demo-1594587805707x531141759021875200

It’s late here now, but I’ll provide more explication later. In the meantime, go play with that plugin.(And open the console while you do it. You’ll see.Install the plugin in a project and send it different input lists and observe what happens.)

I appreciate your work and that you tried to replicate it, thank you!

Did you read the thread’s last post I sent over maybe this clears it up for you of what should work:

I mean even before I tried to get the length then it did not return the length suddenly it worked. Clear proof of a bug, that you can however not replicate because it is bound to my application/plugin.

Would you not say that if without any changes something suddenly works it is a bug?
I am happy to receive more feedback from you. Again I appreciate the time you put into building the sample plugin highly!