How to have an object in a List

I'm creating a List.
Some items in the list will be a Label, some an InputText but some I would like to have both. Think a terminal window. Some lines just display text, others have a prompt with the ability to have the user enter text. Also, it would be nice for all the items to default to being at the top instead of being centered. The reason the prompt is separate from input is so the user doesn't delete the prompt text.

I was trying to make an object with both a Label and InputText in it. It won't show up.

I've created some test items for the list. Later, it will be more dynamic.

This is the relevant code:

    //Items in the list
    let data = [ ];

    //Prompt text
    let promptLabel = new Label({
        text: "[prompt~]#",
        labelWidth: 100,
        size: 14,
        font: "Arial",
        color: white,
        rollColor: black,
        backgroundColor: black,
    });

    //user input text
    let inputText = new TextInput({
        text: "Type here",
        size: 14,
        font: "Arial",
        color: white,
        backgroundColor: black,
        borderWidth: 0,
        width: 598,
        cursorColor: white,
    });

    //Display only text, full width
    new Label({
        text: "Some text reply from server to display.",
        labelWidth: 700,
        size: 14,
        font: "Arial",
        color: white,
        backgroundColor: black,
        rollColor: black,
    });


    //List item renderers

    //Contains the prompt label and a place for the user to input text
    let inputRenderer = { promptLabel, inputText };

    //Adding some Label lines for testing
    for (var d=0;d<8;d++){
        var txt = new Label({
            text: d+" Some text to display.",
            labelWidth: 700,
            size: 14,
            font: "Arial",
            color: white,
            backgroundColor: black,
            rollColor: black,
        });
        data.push(txt)
    }
   
    //Adding an object with both a label and an input text field
    data.push(inputRenderer)

    //The list
    const displayList = new List({
        list: data,
        viewNum: 10,
        align: LEFT,
        scrollBarActive: true,
        indent: 0,
        labelIndentH: 0,
        backgroundColor: black,
        rollBackgroundColor: black,
        selectedBackgroundColor: black,  
        backdropColor: black,
        selectedRollColor: black,
        rollColor: black,
        currentSelected:false,
        padding: 1,
        noScale: true,
        index: 0,
        width: 750,
        height: 500,
    }).loc(5, 100);
     displayList.scrollBar.size = 20;
    S.update();

It is just your raw JS code. You have push(inputRenderer) but that is an object literal {}. You want to push(promptLabel, inputText). Or change inputRenderer to an array and use concat().

const inputRenderer = [promptLabel, inputText];

// loop code...

data = data.concat(inputRenderer);
1 Like

But I want both items to be on the same list item next to each other - not after each other.

I was trying to have an object with two things in it so that the list would show them in the same list item next to each other.

Is there a way to do that?

There should be two text fields on the same line. One is read only the second is for user input.

I see. The object needs to be a DisplayObject. So - a Container(). Or you can use Tile() - that might make it a touch easier.

image

Those come with the List - but are actually just made from Tile() of a Label, Slider, Stepper, etc.

1 Like

Thank you! I forgot that example.

Well... don't use that specific one... just a Tile of your two things along with the other labels in the List:

const one = new Label("Type here: ", null, null, white);
const two = new TextInput();

STYLE = {valign:CENTER, backdropColor:dark, backdropPaddingV:10}
const pair = new Tile([one, two], 2, 1, 10, 0, true);

STYLE = {align:LEFT, size:35, viewNum:4.5}
new List(550,300, ["Hello", "Goodbye", pair, "again", "and again", "once more"])
    .center();
1 Like

Awesome! Thanks, I understand.

1 Like

This is great. Thank you.

However, only the second instance of a tile will show up in a list. Can I not repeat tiles? I tried this in your editor.

const one = new Label("Type here: ", null, null, white);
const two = new TextInput();

STYLE = {valign:CENTER, backdropColor:dark, backdropPaddingV:10}
const pair = new Tile([one, two], 2, 1, 10, 0, true);

STYLE = {align: LEFT,valign: CENTER, backdropColor: black,};
const responseOnlyLabel = new Label({
text: "Some Response Text",
size: 26,
font: "Arial",
color: white,
backgroundColor: black,
});
let responseOnlyTile = new Tile(
[responseOnlyLabel],
1, //cols
1, //rows
0, //spacingH
0, //spacingV
true, //unique
750, //width
20 //height
);

const Data = ["Hello", pair, pair, responseOnlyTile,responseOnlyTile,"Goodbye" ];

STYLE = {align:LEFT, size:35, viewNum:9}
new List(550,600,Data)
.center();

image

The List does not automatically clone objects, which means it places the object the first time and then moves it the second time.

You can try ["Hello", pair, pair.clone(), responseOnlyTile,responseOnlyTile.clone(),"Goodbye" ];

It depends on how you are handling events, etc.