2

I have an Employees model with first_name and last_name string fields (I'll use John Doe for the example). I'd like to have each line of a drop-down widget read "Doe, John" using the Employees datasource. I can bind the names array of a drop-down widget to one field or the other pretty easily by editing the "names" field of the widget:

=@datasources.Employees.item.last_name yields Doe, and =@datasources.Employees.item.first_name yields John in the dropdown's first list item, respectively.

Concatenating a static string to the field also works:

=@datasources.Employees.item.last_name + "-test" yields Doe-test in the drop-down

However, when I try to modify this binding to combine the two fields, it doesn't work:

=@datasources.Employees.item.last_name + ", " + @datasource.item.Employees.first_name yields just Doe

Even dumping both fields into an array and joining them:

=[@datasources.Employees.item.last_name, @datasources.Employees.item.first_name].join(", ") yields just Doe

The only way I've found to get the values of two different fields from a record together on the same line in a drop-down widget is to use client scripting to populate the names array of the widget during the onDataLoad event:

app.datasources.Employees.load(function() {
  app.datasources.Employees.items.forEach(
    item => widget.names.push([item.last_name, item.first_name].join(", "))
  );
});

Is this the best/only way to do this, or am I just missing something on the names binding dialog? Thanks!

mjblay
  • 108
  • 7

2 Answers2

7

In your dropdown names binding do the following:

(@datasources.Employees.items).map(function(i) { return i.last_name + ', ' + i.first_name; })

That will do what you want.

Markus Malessa
  • 1,841
  • 2
  • 9
  • 11
  • that () before .map() matters, editor just doesn't accept expression w/o (), and Google's document doesn't precise this, thanks Markus. – Albert Aug 04 '19 at 21:17
1

The reason this happens is because the expected value for the names is:

An optional array of option labels that correspond 1-1 with the option values. This is useful if the value set in options and value are not strings, and instead set some underlying data in the backend. For example, if value and options are bound to a record, this could be used to display a certain field of the record to the user.

So the first thing to take into account is, what is the binding of the dropdown options? I assume it would be

@datasource.Employees.items.

If that is so, the next thing we need to take into account is that you need to provide an array that matches the exact same number of items that the options has. Unfortunately, that is not the case when you peform the binding the way you are doing it,

@datasources.Employees.item.last_name + ", " + @datasource.item.Employees.first_name

You are only providing one item instead of an array and this will yield unexpected results depending how your datasources are configured. However, when you do it via client script, you are pushing items into that array and matching the items length of the options datasource, hence it works.

The approach you are using its fine, except you'll have to reload the datasource everytime there is a change. A better way of doing it would be following the answer provided by Markus Malessa. That way, you are providing an array of items that correspond 1-1 with the option values and there is no need for reloading the datasource everytime there is change.

Morfinismo
  • 4,985
  • 4
  • 19
  • 36