@@ -16,10 +16,18 @@ Ext4.define('LABKEY.internal.ViewDesigner.field.FilterTextValueUtil', {
1616 // convert the filter value into a user-editable string using filter.getURLParameterValue()
1717 var valueString = filter . getURLParameterValue ( ) ;
1818
19- // replace ; with \n on UI
19+ // Display multi-valued filters with one value per line in the textarea.
20+ // getURLParameterValue() returns {json:[...]} when values contain the ';' separator,
21+ // so we need to parse that format before converting to newline-separated display.
2022 if ( filterType . isMultiValued ( ) && ( urlSuffix !== 'notbetween' && urlSuffix !== 'between' ) ) {
21- if ( typeof valueString === 'string' && valueString . indexOf ( '\n' ) === - 1 && valueString . indexOf ( ';' ) > 0 )
22- valueString = valueString . replaceAll ( ';' , '\n' ) ;
23+ if ( typeof valueString === 'string' ) {
24+ var parsed = this . _parseJsonFilterValue ( valueString ) ;
25+ if ( parsed !== null ) {
26+ valueString = parsed . join ( '\n' ) ;
27+ } else if ( valueString . indexOf ( '\n' ) === - 1 && valueString . indexOf ( ';' ) > 0 ) {
28+ valueString = valueString . replaceAll ( ';' , '\n' ) ;
29+ }
30+ }
2331 }
2432
2533 this . setValue ( valueString ) ;
@@ -48,15 +56,55 @@ Ext4.define('LABKEY.internal.ViewDesigner.field.FilterTextValueUtil', {
4856
4957 setRecordValue : function ( valueString ) {
5058 // parse the value string into parts for multi-value filters
59+ var filterValue ;
5160 try {
61+ // For multi-valued filters (excluding between/notbetween), values are displayed
62+ // one per line in the textarea. When saving, split by newline only and encode
63+ // using {json:[...]} if any value contains the separator character (e.g. ';')
64+ // to prevent parseValue from incorrectly splitting those values.
65+ var op = this . record . get ( "items" ) [ this . clauseIndex ] . op ;
66+ var filterType = LABKEY . Filter . getFilterTypeForURLSuffix ( op ) ;
67+ var urlSuffix = filterType ? filterType . getURLSuffix ( ) : null ;
68+
69+ if ( filterType && filterType . isMultiValued ( ) && typeof valueString === 'string'
70+ && urlSuffix !== 'notbetween' && urlSuffix !== 'between' ) {
71+ var sep = filterType . getMultiValueSeparator ( ) ;
72+ var values = valueString . split ( '\n' ) ;
73+ if ( sep && values . some ( function ( v ) { return v . indexOf ( sep ) !== - 1 ; } ) ) {
74+ valueString = '{json:' + JSON . stringify ( values ) + '}' ;
75+ } else {
76+ valueString = values . join ( sep ) ;
77+ }
78+ }
79+
5280 var filter = this . createFilter ( valueString ) ;
53- var filterValue = filter . getValue ( ) ;
81+ filterValue = filter . getValue ( ) ;
5482 }
5583 catch ( e ) {
5684 console . warn ( "Error parsing filter value: " + valueString ) ;
5785 filterValue = valueString ;
5886 }
5987
6088 this . record . get ( "items" ) [ this . clauseIndex ] . value = filterValue ;
89+ } ,
90+
91+ /**
92+ * GitHub Issue 947: Multi value text choice values with semicolon mangled in LKS grid view editor
93+ * Parse a {json:[...]} encoded filter value string.
94+ * Returns the parsed array, or null if the string is not in {json:...} format.
95+ */
96+ _parseJsonFilterValue : function ( valueString ) {
97+ if ( typeof valueString === 'string'
98+ && valueString . indexOf ( '{json:' ) === 0
99+ && valueString . lastIndexOf ( '}' ) === valueString . length - 1 ) {
100+ try {
101+ var parsed = JSON . parse ( valueString . substring ( '{json:' . length , valueString . length - 1 ) ) ;
102+ if ( Array . isArray ( parsed ) )
103+ return parsed ;
104+ } catch ( e ) {
105+ // Not valid JSON, return null to fall through to default handling
106+ }
107+ }
108+ return null ;
61109 }
62110} ) ;
0 commit comments