Skip to content

Commit

Permalink
Fix view mode rendering of select2Many/selectMany #256
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisala committed Jul 11, 2024
1 parent 34ffb7c commit b362334
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 8 deletions.
15 changes: 15 additions & 0 deletions grails-app/assets/javascripts/forms-knockout-bindings.js
Original file line number Diff line number Diff line change
Expand Up @@ -1146,6 +1146,21 @@
ecodata.forms.OutputListSupport.apply(target, [options.metadata, options.constructorFunction, options.context, options.userAddedRows, options.config]);
};

/**
* The role of this extender is to provide a function the view model can use to render a list of
* values selected using a multi select component (select2Many / selectMany) that have also used a
* label/value configuration for the options.
* @param target the observable.
* @param options unused
*/
ko.extenders.toReadOnlyString = function(target, options) {
target.toReadOnlyString = function() {
var values = ko.utils.unwrapObservable(target);
var labels = target.constraints && _.isFunction(target.constraints.label) ? _.map(values, target.constraints.label) : values;
return labels.join(', ');
}
}

/**
* This is kind of a hack to make the closure config object available to the any components that use the model.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -732,7 +732,8 @@ class ModelJSTagLib {
}

def stringListViewModel(JSModelRenderContext ctx) {
observableArray(ctx)
String extender = '{toReadOnlyString:true}'
observableArray(ctx, [extender])
}

def setViewModel(JSModelRenderContext ctx) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,23 @@ class ViewModelWidgetRenderer implements ModelWidgetRenderer {
context.writer << "<span ${context.attributes.toString()} data-bind='${context.databindAttrs.toString()}'></span>"
}

/**
* The binding looks for the toReadOnlyString function because there exist some misconfigurations that
* use a "text" data model item with a selectMany/select2Many view. This is a workaround to prevent exceptions.
*/
private static String selectManyBindingString(WidgetRenderContext context) {
'_.isFunction(('+context.source+' || []).toReadOnlyString) ? '+ context.source+'.toReadOnlyString() : ('+context.source+'() || []).join(", ")'
}

@Override
void renderSelectMany(WidgetRenderContext context) {
context.databindAttrs.add 'text', '('+context.source+'() || []).join(", ")'
context.databindAttrs.add 'text',selectManyBindingString(context)
context.writer << "<span ${context.attributes.toString()} data-bind='${context.databindAttrs.toString()}'></span>"
}

@Override
void renderSelect2Many(WidgetRenderContext context) {
context.databindAttrs.add 'text', selectManyBindingString(context)
context.writer << "<span ${context.attributes.toString()} data-bind='${context.databindAttrs.toString()}'></span>"
}

Expand Down Expand Up @@ -195,12 +209,6 @@ class ViewModelWidgetRenderer implements ModelWidgetRenderer {
context.writer << """\$<span data-bind='${context.databindAttrs.toString()}'></span>.00"""
}

@Override
void renderSelect2Many(WidgetRenderContext context) {
context.databindAttrs.add 'text', '('+context.source+'() || []).join(", ")'
context.writer << "<span ${context.attributes.toString()} data-bind='${context.databindAttrs.toString()}'></span>"
}

@Override
void renderMultiInput(WidgetRenderContext context) {
context.databindAttrs.add 'text', '('+context.source+'() || []).join(", ")'
Expand Down

0 comments on commit b362334

Please sign in to comment.