diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/extraction_rules/edit_extraction_rule.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/extraction_rules/edit_extraction_rule.tsx index fa69e05bd65fd..c32e495f3f889 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/extraction_rules/edit_extraction_rule.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/extraction_rules/edit_extraction_rule.tsx @@ -298,9 +298,34 @@ export const EditExtractionRule: React.FC = ({ ( + rules={{ + validate: (rule) => { + if (!rule?.trim()) { + return i18n.translate( + 'xpack.enterpriseSearch.content.indices.extractionRules.editContentField.fieldInput.requiredError', + { + defaultMessage: 'A value is required.', + } + ); + } + + if (rule[0] !== '/') { + return i18n.translate( + 'xpack.enterpriseSearch.content.indices.extractionRules.editContentField.fieldInput.slashMissingError', + { + defaultMessage: 'Value must begin with a /.', + } + ); + } + + return true; + }, + }} + render={({ field, fieldState: { error, isTouched } }) => ( <> = ({ = ({ data-telemetry-id="entSearchContent-crawler-domainDetail-extractionRules-saveExtractionRule" type="submit" onClick={() => saveRule({ ...getValues() })} - disabled={!formState.isValid} + disabled={!formState.isValid || !rulesFields || rulesFields.length === 0} > {i18n.translate( 'xpack.enterpriseSearch.content.indices.extractionRules.editRule.saveButtonLabel', diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/extraction_rules/edit_field_rule_flyout.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/extraction_rules/edit_field_rule_flyout.tsx index 253d66d63820f..c5bad553ab0f6 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/extraction_rules/edit_field_rule_flyout.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/extraction_rules/edit_field_rule_flyout.tsx @@ -227,28 +227,39 @@ export const EditFieldRuleFlyout: React.FC = ({ {!!field.value && ( <> - - ( + + !!rule?.trim() || + i18n.translate( + 'xpack.enterpriseSearch.content.indices.extractionRules.editContentField.fieldInput.requiredError', + { + defaultMessage: 'A value is required.', + } + ), + }} + render={({ field: selectorField, fieldState: { error, isTouched } }) => ( + = ({ onChange={selectorField.onChange} value={selectorField.value ?? ''} /> - )} - /> - + + )} + /> {field.value === FieldType.HTML ? ( = ({ ( + rules={{ + validate: (rule) => + !!rule?.trim() || + i18n.translate( + 'xpack.enterpriseSearch.content.indices.extractionRules.editContentField.contentFixedValue.requiredError', + { + defaultMessage: 'A value is required', + } + ), + }} + render={({ + field: valueField, + fieldState: { error: fieldError, isTouched: fieldIsTouched }, + }) => ( = ({