- Published on
A React component for finding matches within a split string
- Authors
- Name
- Tom Southall
- @tomsouthall
Today I published a React component to npm called split-match which has proven handy for a larger autocomplete component I am currently working on.
Introduction
SplitMatch
splits a supplied string into multiple React elements delimited by the supplied separator
prop. In and of itself this is no big deal! But, it also converts any text that matches a searchText
prop into a React element, even when the matched text is divided across the elements created by the split. If this makes no sense, read on...
Why would I need this?
SplitMatch
is particularly useful for building components like an autocomplete, where the text entered is highlighted in the accompanying listbox options:
The markup for the example above is simple. Each listbox option looks something like this, with the <strong>
element denoting the matched search text:
<li><strong>New Yor</strong>k City, New York, United States</li>
Converting this into a React component would be straightforward.
However, what if we wanted to pretty things up a little and apply some formatting to our listbox options? We may want the state and country names to appear in a smaller font than the city name, like in this SplitMatch
example:
Here we may need to take a string such as "Springfield, Michigan, United States"
and split it at the first comma so we can apply different styling to each element. For example:
<li>
<span class="split1">Springfield,</span>
<span class="split2"> Michigan, United States</span>
</li>
Things get complicated when we add the text matching back, because the matched text may span across more than one of the splits. An example in this case would be a search for "Springfield, Mi"
. Given all the Springfields in the United States (incidentally it's 34!), the likelihood is you'd need to type past the comma to find your match. This would require listbox markup such as this:
<li>
<span class="split1"><strong>Springfield,</strong></span>
<span class="split2"><strong> Mi</strong>chigan, United States</span>
</li>
Here's where the SplitMatch
component comes in handy. It takes a string, a separator character and some search text and converts it into customisable React Elements with markup such as the example above.
This allows lots of flexibility in formatting and at the same time allows matched text to be easily displayed, even when it is split between different block elements. Note that in this example, you can also choose whether to hide the delimiter/separator character, in this case the first comma in the top listbox option.
Installation & Usage
Installing
$ npm install split-match
Usage
Basic Example:
import React from 'react'
import SplitMatch from 'split-match'
export default ListboxOption = () => {
return (
<li>
<SplitMatch searchText={'New York City, New'} separator=",">
New York City, New York, United States
</SplitMatch>
</li>
)
}
This would produce the following markup inside the <li>
element:
<span><strong>New York City,</strong></span>
<span><strong> New</strong> York,</span>
<span> United States</span>
Full Example:
import React from 'react'
import SplitMatch from 'split-match'
const SplitComponent = (props) => {
const { children, index } = props
return <div className={`split${index}`}>{children}</div>
}
const MatchComponent = (props) => {
const { children } = props
return <span className={'match'}>{children}</span>
}
export default ListboxOption = () => {
return (
<li>
<SplitMatch
caseSensitiveMatch={false}
caseSensitiveSplit={false}
globalMatch={false}
globalSplit={false}
includeSeparator={false}
searchText={'new york city, new'}
separator=","
MatchComponent={MatchComponent}
SplitComponent={SplitComponent}>
New York City, New York, United States
</SplitMatch>
</li>
)
}
This would produce the following markup inside the <li>
element:
<div class="split0"><span class="match">New York City</span></div>
<div class="split1"><span class="match"> New</span> York, United States</div>
API
The following props can be supplied to the <SplitMatch>
component:
caseSensitiveMatch
- Type:
boolean
- Default:
false
- If
true
thesearchText
value is matched with case sensitivity applied.
caseSensitiveSplit
- Type:
boolean
- Default:
false
- If
true
theseparator
character is searched for with case sensitivity applied.
globalMatch
- Type:
boolean
- Default:
true
- If
true
every instance ofsearchText
is matched in the supplied string. - If
false
only the first instance ofsearchText
is matched in the supplied string.
globalSplit
- Type:
boolean
- Default:
true
- If
true
the supplied string is split at every instance ofseparator
. - If
false
the supplied string is split only at the first instance ofseparator
.
includeSeparator
- Type:
boolean
- Default:
true
- Whether or not to include or remove the
separator
character(s) within the supplied string. - If
true
theseparator
remains in the supplied string. - If
false
theseparator
is removed from supplied string. IfglobalSplit
is alsotrue
, all instances ofseparator
are removed. IfglobalSplit
isfalse
, only the first instance ofseparator
is removed.
searchText
- Type:
string
- Default:
''
- This text is matched within the larger string.
- Use
globalMatch
to determine whether to match every instance ofsearchText
in the string, or just the first instance. If the search text is case sensitive, specify usingcaseSensitiveMatch
.
separator
- Type:
string
- Default:
','
- It is recommended that this be a single character delimiter, by which to split the supplied string. Use
globalSplit
to determine whether to split at every instance ofseparator
or just the first instance. If the separator is case sensitive, specify usingcaseSensitiveSplit
.
The following components can be supplied to the <SplitMatch>
component as props:
MatchComponent
- Type: React Component
- Default:
undefined
- This component is passed the following props:
children
- The matched text string
- This is a customisable wrapper element (or elements) for the matched text
SplitComponent
- Type: React Component
- Default:
undefined
- This component is passed the following props:
children
(string) - The matched text stringindex
(number) - The index of the split text (starts at0
)
- This is a customisable wrapper element (or elements) for the split text