atk4 / ui

Robust and easy to use PHP Framework for Web Apps
https://atk4-ui.readthedocs.io
MIT License
441 stars 106 forks source link

Dropdown Value decoration #268

Open romaninsh opened 6 years ago

romaninsh commented 6 years ago

Here is my current proposal:

1. Add "values" property for Model Field.

This will be change in Agile Data, which would allow to specify list of allowed properties (derived from keys of $value array) as well as set default presentation for UI.

$model->addField('gender', ['values'=>['F'=>'Female', 'M'=>'Male']]);

Effect would be similar to:

$model->addField('gender', [
    'enum'=>['F', 'M'],
    'ui'=>['values'=>['F'=>'Female', 'M'=>'Male']]
]);

2. Add formatter

When defining Model Field, through 'ui' array you should be able to define a format of how the field is presented.

$model->hasOne('country_id',[
    new Country(),
    'ui'=>['format'=>'<i class="{$country_code} flag"></i>{$country}']
])->addFields(['country_code', 'country']);

This will result in Dropdown, Autocomplete and Table column values to display values with icons:

screen shot 2017-11-15 at 17 17 12

(This must not conflict with https://github.com/atk4/data/issues/252) (Will use https://github.com/atk4/ui/blob/develop/src/TableColumn/Template.php and https://github.com/atk4/ui/blob/develop/src/Lister.php)

3. Allow formatter callback

With a sensible callback, you should be able to use different ways to decorate. Output of a callback may be a string or a Template object, in which case it will still be populated with the values.

$model->hasOne('country_id',[
    new Country(),
    'ui'=>['format'=>function($m){
        if($m['is_eu']) { 
            return '<i class="eu flag"></i>'.htmlspecialchars($m['country']);
        } else {
            return new Template('<i class="{$country_code} flag"></i>{$country}');
        }
    }]
])->addFields(['country_code', 'country']);

4. May be combined with manual mapping:

This technically can be packed up into a new field class, so you don't have to re-type every time:

$model->addField('country_id',[
    'values'=>['uk'=>['country_code'=>'gb', 'country'=>'United Kingdom']],
    'ui'=>['format'=>'<i class="{$country_code} flag"></i>{$country}']
]);

5. Track fields properly

As you import fields you may use different aliases. Code must work consistently in Table (where it works with $row model) and Dropdown (where it works with referenced model)

$model->hasOne('country_id',[
    new Country(),
    'ui'=>['format'=>'<i class="{$code} flag"></i>{$title}']
])->withTitle()->addFields(['code'=>'country_code']);

6. Can store data for other uses

A {$_} could be a tag which is set automatically to a the title field. Similarly {$_id} could refer to $model->id_field.

$model->hasOne('country_id',[
    new Country(),
    'ui'=>['format'=>'<div data-currency="{$currency}"></div>{$_}']
])->withTitle()->addField('currency');

NOT INCLUDED (yet):


OLD DESCRIPTION

We need a way to decorate drop-down and auto-complete values correctly. Unlike "Persistence/UI.php" which we use to convert "date" object into presentable string and back, values for drop-downs and auto-completes does not have to be read back. Also for the table value interpretation is important.

On other hand, sometimes values may include multiple fields and may be formatted differently. So lets say auto-complete field could contain a template like this:

"Invoice {$invoice_no} dated {$date}"

This could be rendered as string and perhaps even contain HTML. This can theoretically even be a callback. Works for Tables also.

But drop-downs may use some icons etc.

  <div class="item" data-value="dk"><i class="dk flag"></i>Denmark</div>
  <div class="item" data-value="dj"><i class="dj flag"></i>Djibouti</div>
  <div class="item" data-value="dm"><i class="dm flag"></i>Dominica</div>

I suppose we could use '<i class="{$country_code} flag"></i>{$country}' value here, right?

acicovic commented 5 years ago

In my opinion those are great ideas. Point 1 seems to work already. Point 2 doesn't seem to work. For starters, having point 2 would be awesome.