Skip to content

Commit 9cbc487

Browse files
committed
Merge branch 'devangbhavsar89-dev' into dev
2 parents a3e0656 + a5a90c6 commit 9cbc487

File tree

7 files changed

+78
-7
lines changed

7 files changed

+78
-7
lines changed

docs/documentation/docs/controls/TaxonomyPicker.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ The TaxonomyPicker control can be configured with the following properties:
165165
| termActions | ITermActions | no | Allows to execute custom action on the term like e.g. get other term labelsITermActions. |
166166
| hideTagsNotAvailableForTagging | boolean | no | Specifies if the tags marked with 'Available for tagging' = false should be hidden |
167167
| validateOnLoad | boolean | no | Specifies if the initial values will be validated, when the component is loaded. Default value is false |
168+
| validateInput | boolean | no | Specifies if the input text will be validated, when the component focus is changed |
168169
| hideDeprecatedTags | boolean | no | Specifies if deprecated tags should be hidden |
169170
| placeholder | string | no | Short text hint to display in empty picker |
170171
| errorMessage | string | no | Static error message displayed below the picker. Use `onGetErrorMessage` to dynamically change the error message displayed (if any) based on the current value. `errorMessage` and `onGetErrorMessage` are mutually exclusive (`errorMessage` takes precedence). |

src/controls/taxonomyPicker/ITaxonomyPicker.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@ export interface ITaxonomyPickerProps {
8484
*/
8585
validateOnLoad?: boolean;
8686

87+
/**
88+
* Specifies if the input text will be validated, when the component focus is changed
89+
*/
90+
validateInput?: boolean;
91+
8792
/**
8893
* The method is used to get the validation error message and determine whether the input value is valid or not.
8994
* Mutually exclusive with the static string errorMessage (it will take precedence over this).

src/controls/taxonomyPicker/TaxonomyPicker.tsx

Lines changed: 61 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import * as React from 'react';
22
import { PrimaryButton, DefaultButton, IconButton } from 'office-ui-fabric-react/lib/Button';
33
import { Panel, PanelType } from 'office-ui-fabric-react/lib/Panel';
44
import { Spinner, SpinnerSize } from 'office-ui-fabric-react/lib/Spinner';
5+
import { Autofill } from 'office-ui-fabric-react/lib/components/Autofill/Autofill';
56
import { Label } from 'office-ui-fabric-react/lib/Label';
67
import TermPicker from './TermPicker';
78
import { IPickerTerms, IPickerTerm } from './ITermPicker';
@@ -32,6 +33,7 @@ export const TERM_IMG = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQC
3233
export class TaxonomyPicker extends React.Component<ITaxonomyPickerProps, ITaxonomyPickerState> {
3334
private termsService: SPTermStorePickerService;
3435
private previousValues: IPickerTerms = [];
36+
private invalidTerm: string = null;
3537
private cancel: boolean = true;
3638

3739
/**
@@ -55,6 +57,9 @@ export class TaxonomyPicker extends React.Component<ITaxonomyPickerProps, ITaxon
5557
this.onSave = this.onSave.bind(this);
5658
this.termsChanged = this.termsChanged.bind(this);
5759
this.termsFromPickerChanged = this.termsFromPickerChanged.bind(this);
60+
this.onInputChange = this.onInputChange.bind(this);
61+
this.onBlur = this.onBlur.bind(this);
62+
5863
this.termsService = new SPTermStorePickerService(this.props, this.props.context);
5964
}
6065

@@ -100,7 +105,6 @@ export class TaxonomyPicker extends React.Component<ITaxonomyPickerProps, ITaxon
100105
* it checks, if all entries still exist in term store. if allowMultipleSelections is true. it have to validate all values
101106
*/
102107
private async validateTerms(): Promise<void> {
103-
104108
const {
105109
hideDeprecatedTags,
106110
hideTagsNotAvailableForTagging,
@@ -140,8 +144,6 @@ export class TaxonomyPicker extends React.Component<ITaxonomyPickerProps, ITaxon
140144
* Loads the list from SharePoint current web site
141145
*/
142146
private loadTermStores(): void {
143-
144-
145147
if (this.props.termActions && this.props.termActions.initialize) {
146148
this.props.termActions.initialize(this.termsService);
147149
// this.props.termActions.actions.forEach(x => {
@@ -275,6 +277,58 @@ export class TaxonomyPicker extends React.Component<ITaxonomyPickerProps, ITaxon
275277
this.validate(terms);
276278
}
277279

280+
/**
281+
* Shows an error message for any invalid input inside taxonomy picker control
282+
*/
283+
private validateInputText(): void {
284+
// Show error message, if any unresolved value exists inside taxonomy picker control
285+
if (!!this.invalidTerm) {
286+
// An unresolved value exists
287+
this.setState({
288+
errorMessage: strings.TaxonomyPickerInvalidTerms.replace('{0}', this.invalidTerm)
289+
});
290+
}
291+
else {
292+
// There are no unresolved values
293+
this.setState({
294+
errorMessage: null
295+
});
296+
}
297+
}
298+
299+
/**
300+
* Triggers when input of taxonomy picker control changes
301+
*/
302+
private onInputChange(input: string): string {
303+
if (!input) {
304+
const { validateInput } = this.props;
305+
if (!!validateInput) {
306+
// Perform validation of input text, only if taxonomy picker is configured with validateInput={true} property.
307+
this.invalidTerm = null;
308+
this.validateInputText();
309+
}
310+
}
311+
return input;
312+
}
313+
314+
/**
315+
* Triggers when taxonomy picker control loses focus
316+
*/
317+
private onBlur(event: React.FocusEvent<HTMLElement | Autofill>): void {
318+
const { validateInput } = this.props;
319+
if (!!validateInput) {
320+
// Perform validation of input text, only if taxonomy picker is configured with validateInput={true} property.
321+
const target: HTMLInputElement = event.target as HTMLInputElement;
322+
const targetValue = !!target ? target.value : null;
323+
if (!!targetValue) {
324+
this.invalidTerm = targetValue;
325+
}
326+
else {
327+
this.invalidTerm = null;
328+
}
329+
this.validateInputText();
330+
}
331+
}
278332

279333
/**
280334
* Gets the given node position in the active nodes collection
@@ -317,7 +371,6 @@ export class TaxonomyPicker extends React.Component<ITaxonomyPickerProps, ITaxon
317371
}
318372

319373
private validate = async (value: IPickerTerms): Promise<void> => {
320-
321374
//
322375
// checking if there are any invalid nodes left after initial validation
323376
//
@@ -389,7 +442,8 @@ export class TaxonomyPicker extends React.Component<ITaxonomyPickerProps, ITaxon
389442
disabled,
390443
isTermSetSelectable,
391444
allowMultipleSelections,
392-
disabledTermIds, disableChildrenOfDisabledParents,
445+
disabledTermIds,
446+
disableChildrenOfDisabledParents,
393447
placeholder,
394448
panelTitle,
395449
anchorId,
@@ -418,6 +472,8 @@ export class TaxonomyPicker extends React.Component<ITaxonomyPickerProps, ITaxon
418472
value={activeNodes}
419473
isTermSetSelectable={isTermSetSelectable}
420474
onChanged={this.termsFromPickerChanged}
475+
onInputChange={this.onInputChange}
476+
onBlur={this.onBlur}
421477
allowMultipleSelections={allowMultipleSelections}
422478
disabledTermIds={disabledTermIds}
423479
disableChildrenOfDisabledParents={disableChildrenOfDisabledParents}

src/controls/taxonomyPicker/TermPicker.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import * as strings from 'ControlStrings';
99
import { Icon } from 'office-ui-fabric-react/lib/Icon';
1010
import { ExtensionContext } from '@microsoft/sp-extension-base';
1111
import { ITermSet } from "../../services/ISPTermStorePickerService";
12+
import { Autofill } from 'office-ui-fabric-react/lib/components/Autofill/Autofill';
1213

1314
export class TermBasePicker extends BasePicker<IPickerTerm, IBasePickerProps<IPickerTerm>>
1415
{
@@ -31,6 +32,8 @@ export interface ITermPickerProps {
3132
placeholder?: string;
3233

3334
onChanged: (items: IPickerTerm[]) => void;
35+
onInputChange: (input: string) => string;
36+
onBlur: (ev: React.FocusEvent<HTMLElement | Autofill>) => void;
3437
}
3538

3639
export default class TermPicker extends React.Component<ITermPickerProps, ITermPickerState> {
@@ -182,22 +185,23 @@ export default class TermPicker extends React.Component<ITermPickerProps, ITermP
182185
}
183186
}
184187

185-
186188
/**
187189
* gets the text from an item
188190
*/
189191
private onGetTextFromItem(item: any): any {
190192
return item.name;
191193
}
192194

193-
/**
195+
/**
194196
* Render method
195197
*/
196198
public render(): JSX.Element {
197199
const {
198200
disabled,
199201
value,
200202
onChanged,
203+
onInputChange,
204+
onBlur,
201205
allowMultipleSelections,
202206
placeholder
203207
} = this.props;
@@ -217,6 +221,8 @@ export default class TermPicker extends React.Component<ITermPickerProps, ITermP
217221
defaultSelectedItems={value}
218222
selectedItems={terms}
219223
onChange={onChanged}
224+
onInputChange={onInputChange}
225+
onBlur={onBlur}
220226
itemLimit={!allowMultipleSelections ? 1 : undefined}
221227
className={styles.termBasePicker}
222228
inputProps={{

src/loc/en-us.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ define([], () => {
4646
"TaxonomyPickerInLabel": "in",
4747
"TaxonomyPickerTermSetLabel": "Term Set",
4848
"TaxonomyPickerTermsNotFound": "The next selected term(s) could not be found in the term store: {0}",
49+
"TaxonomyPickerInvalidTerms": "Please fix invalid term(s): {0}",
4950

5051
peoplePickerComponentTooltipMessage: "People Picker",
5152
peoplePickerComponentErrorMessage: "Required Field",

src/loc/mystrings.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ declare interface IControlStrings {
2727
TaxonomyPickerInLabel: string;
2828
TaxonomyPickerTermSetLabel: string;
2929
TaxonomyPickerTermsNotFound: string;
30+
TaxonomyPickerInvalidTerms: string;
3031

3132
ListItemPickerSelectValue: string;
3233

src/webparts/controlsTest/components/ControlsTest.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -730,6 +730,7 @@ export default class ControlsTest extends React.Component<IControlsTestProps, IC
730730
onChange={this.onServicePickerChange}
731731
isTermSetSelectable={false}
732732
placeholder="Select service"
733+
// validateInput={true} /* Uncomment this to enable validation of input text */
733734
required={true}
734735
errorMessage='this field is required'
735736
onGetErrorMessage={(value) => { return 'comment errorMessage to see this one'; }}

0 commit comments

Comments
 (0)