formly-js / angular-formly-templates-lumx

LumX Templates for Angular-Formly
https://af-lumx.herokuapp.com/
MIT License
35 stars 13 forks source link

Object-less simple string model for lx-select #9

Closed charandas closed 9 years ago

charandas commented 9 years ago

I tried going through several iterations with lx-select, by varying the choice and selected in templateOptions. My ng-model gets set to an object. Is it possible to declarative say, I just want the field value plucked for ng-model for the following scenario:

"options": [
        "choice": "name",
        "selected": "value",
          {
            "name": "In Service",
            "value": "inService"
          },
          {
            "name": "Maintenance",
            "value": "maintenance"
          },
          {
            "name": "Out of Service",
            "value": "outOfService"
          },
          {
            "name": "Pending",
            "value": "pending"
          }
        ]

Or do I have to make a custom template for this scenario? Seems to me, it could a widely adopted use-case?

kentcdodds commented 9 years ago

FYI, I have a fairly flexible approach in my own project. Maybe it'll be helpful. Looks like this (ES6 warning):

export default ngModule => {
  const template =
    `<select ng-model="model[options.key]" class="form-control">
      <option ng-if="!to.notNull" value=""></option>
    </select>`;
  ngModule.run((formlyConfig) => {
    formlyConfig.setType({
      name: 'select',
      extends: 'azBase',
      template,
      defaultOptions(options) {
        const forWithFilter = `for item in to.options | azDynamicFilter:to.filter:to.orderBy`;
        let ngOptions = `item[to.valueProp] as item[to.displayProp || 'name'] ${forWithFilter}`;
        const {valueProp, displayProp, options: items} = options.templateOptions;
        if (items && typeof items[0] === 'string') {
          ngOptions = `item for item in to.options | azDynamicFilter:to.filter:'toString()'`;
        } else if (valueProp === null && displayProp) {
          ngOptions = `item as item[to.displayProp] ${forWithFilter}`;
        }
        return {
          ngModelAttrs: {
            [ngOptions]: {
              value: 'ng-options'
            }
          },
          templateOptions: {
            filter: 'orderBy',
            orderBy: 'name',
            displayProp: 'name',
            valueProp: 'value'
          }
        };
      }
    });
  });
};
charandas commented 9 years ago

Thanks @kentcdodds . I am also using ES6 - definitely helps :+1:

I got this accomplished with the following:

const template =
            `<div class="aftl-select">
                <h3 ng-if="::to.label"><label>
                    {{to.label}} {{::to.required ? '*' : ''}}
                </label></h3>
                <lx-select ng-model="model[options.key]"
                           choices="to.options"
                           model-to-selection="to.modelToObject(data, to.options, callback)"
                           selection-to-model="to.objectToModel(data, to.options, callback)"
                           placeholder="{{::to.placeholder}}"
                           min-length="::to.minLength"
                           allow-clear="::to.allowClear"
                           ng-attr-multiple="{{::to.multiple}}">

                    <lx-select-selected>
                        {{$selected[to.selected] || $selected}} {{::to.selected2 ? ' - ' +
                        $selected[to.selected2] : ''}}
                    </lx-select-selected>

                    <lx-select-choices>
                        {{$choice[to.choice] || $choice}} {{::to.choice2 ? ' - ' +
                        $choice[to.choice2] : ''}}
                    </lx-select-choices>

                </lx-select>
            </div>`

        formlyConfig.setType({
            name: 'select',
            extends: 'lx-select',
            template: template,
            defaultOptions(options) {
                return {
                    templateOptions: {
                        // Called every time the value changes
                        objectToModel: (object, options, callback) =>
                        {
                            // because the model is of string type on init
                            if (typeof object === 'string') {
                                callback(object)
                            } else { // later calls would have the actual object as specified in choices
                                callback(object.value)
                            }

                        },
                        // Only called on init, when model is a string value
                        modelToObject: (model, options, callback) =>
                        {
                            callback(_.find(options, {value: model}))
                        }
                    }
                }
            }
        })
kentcdodds commented 9 years ago

Glad it helped! :-)

(Sent from my mobile device, please forgive typos or brevity) On Apr 9, 2015 10:32 AM, "Karan Batra-Daitch" notifications@github.com wrote:

Closed #9 https://github.com/formly-js/angular-formly-templates-lumx/issues/9.

— Reply to this email directly or view it on GitHub https://github.com/formly-js/angular-formly-templates-lumx/issues/9#event-277232801 .