Slot Scope Props Vue
- Slot Scope Props Vue Download
- Slot-scope= Props Vuetify
- Vue Slot-scope Props Not Defined
- Slot Scope Props Vueling
When Vue 2.6.0 was released, Vue introduced a new unified syntax which is (the v-slot directive) for named and scoped slots. It replaced the slot and slot-scope attributes, which has been deprecated, though not removed, they are still document. Vue template 中 slot-scope/scope 的使用. Vue template 中 slot-scope/scope 的使用在vue 2.5.0+ 中slot-scope替代了 scope template 的使用情形为,我们已经封装好一个组件,预留了插槽,使用 的插槽. 首先 我们的创建一个组件 组件很简单有一个 slot,slot有两个属性 a=123,b=msg. Javascript, ES6, Advanced Vue.js. 하위 컴포넌트인 태그의 슬롯 영역에 slot-scope 속성을 정의하였습니다. 여기서 사용한 변수 scopeProps는 하위 컴포넌트에서 올려준 값을 받기 위한 임의의 변수입니다. #Slot Content Vue implements a content distribution API inspired by the Web Components spec draft(opens new window), using the slotelement to serve as distribution outlets for content. This allows you to compose components like this. The v-slot directive was introduced in Vue 2.6.0, offering an improved, alternative API to the still-supported slot and slot-scope attributes. The full rationale for introducing v-slot is described in this RFC.
The ValidationProvider
component is a regular component that wraps your inputs and provides validation state using scoped slots.
TIP
The slots syntax has been changed in Vue 2.6, the following examples use the new v-slot
syntax instead of the deprecated slot-scope
, but it is still supported and you can use it. However v-slot
have different semantics, consult the Vue docs for more information.
Using the ValidationProvider offers isolated scope for each field validation state, and does not inject/mutate anything outside its slot. You can import it and use whenever you need it. Using the validation context will allow you to apply classes, flags and pass state to your template.
Here is a quick example:
It also works for custom components and solves the issue of authoring self validated components, which is hard to achieve normally because of the directive limitations.
TIP
The fields being validated must have a v-model
so the component can correctly identify the element/component being validated unless the field accepts a file.
# Rendering
By default, ValidationProvider renders a span
, Consider the following example:
The default tag can be changed using the provider's tag
prop.
# Renderless
Sometimes it is unsuitable for a Provider component in principle to render anything extra, because of limitations in the Vue rendering engine we cannot have multiple root nodes which limits the design choice to move away from renderless at the moment, in Vue 3.x it this may change with fragments.
In 2.2.10 a slim
prop can be used to force the component to be renderless, by default it is set to false
.
Note that only the first child will be rendered when slim
is used, any other nodes will be dropped as you cannot have multiple root nodes in a renderless component. Be mindful of that when using the slim
prop.
# Scoped Slot Data
The object passed down to the slot scope is called the validation context. It has the following properties:
Name | Type | Description |
---|---|---|
errors | string[] | The list of error messages. |
failedRules | [x: string]: string | A map object of failed rules with (rule, message) as a (key, value) |
valid | boolean null | The current validation state. |
flags | { [x: string]: boolean } | The flags map object state. |
aria | { [x: string]: string } | Map object of aria attributes for accessibility. |
classes | { [x: string]: boolean } | Map object of the classes configured based on the validation state. |
validate | (e: any) => Promise | A function that is used as an event handler to trigger validation. Useful for fields that do not use v-model. |
reset | () => void | A function that resets the validation state on the provider. |
Since slot scopes can take advantage of ES6 destructing, you can opt-in for any of those properties and pass down to your slot template as you see fit. The example above only needed the errors
array.
# Examples
The previous quick sample validates simple HTML inputs, lets take this up a notch and validate popular 3rd party components like Vuetify's TextInput.
# Basic Example
This passes error messages down to Vuetify's text field component.
# Manual Validation
Triggering validation on any of the providers is simple, but it is opt-in. Meaning you need to explicitly call the validation on the provider instance. Using refs and the public methodvalidate
makes it straight forward.
If you only plan to trigger manual validation using the UI, you can use the validate
handler on the v-slot data to trigger validation without having to use refs
.
Note that the validate
method on the validation handler, you can use the $event
in the Vue template to reference the event arg that is emitted with the event if your handlers are more complex.
# Validation Result
The validate
method returns a validation result wrapped in a promise, so normally you either would use then
or await
for the validation to finish. The validation result contains useful information about the validation attempt:
TIP
Using the same approach you can reset validation state for the provider using the public method reset()
and the slot scope method of the same name.
# File Validation
While v-model
is generally required when using the ValidationProvider component, some inputs like file
do not benefit from having v-model
. Instead, you can use the manual validate
method to avoid having to use v-model
in this instance.
# Input Groups (Checkbox/Radio)
Like radio inputs and (sometimes) checkboxes, some inputs behave as a single input entity. You can wrap a whole group of inputs given that they have the same v-model
in a single ValidationProvider component. You can group as many inputs as you want inside the ValidationProvider component.
# Cross-Field Validation
When using the directive, the confirmed
rule targets the other field that has a corresponding ref
. Using the ValidationProvider is slightly different; it looks for a ValidationProvider component that has a matching vid
prop. The vid
can be either a number or a string.
# Refactoring Validation Providers
While the ValidationProvider has its advantages, it is more verbose than using the v-model
directive, and can be very annoying when creating large forms. There are a couple of ways to address this issue.
# Creating Higher-Order Components
A common pattern in React is to use higher-order components to produce new components with slightly different behavior. This is similar to creating a wrapper or a mixin for our component, except it uses props/events to communicate state.
The withValidation
method takes a component as an argument and creates a new one with the validation behavior enabled. Let's create a VTextFieldWithValidation
using this method:
TIP
Note that the second parameter is a function that transforms the validation context to props object to be passed to the wrapped component. In this case we want to pass the errors
array as the error-messages
prop to the VTextField
component.
With this approach the last example becomes:
WARNING
This approach has some cons, for example if the wrapped component accepts props that have the same name as the ValidationProvider
component. while it will receive these props, they may be of different types, which could lead to serious issues. The problem with HOCs are that you need to be aware of the underlying component's implementation. This can be problematic when working with 3rd party components.
# Wrapping Components Manually
Instead we can wrap the field component with the ValidationProvider in a new component. This is easier and more flexible, and avoids some of the potential problems with Higher-Order components.
Consider this new VTextFieldWithValidation
component.
Ideally you would pass the props you need to either the ValidationProvider
or the VTextField
being validated, with this approach solves the verbosity problem while preserving the simple scoped slots API. It also allows you to distribute props without the issues of having a conflict, unlike HOC.
Using either of these approaches is at your preference.
# Persisting Provider Errors
Sometimes when building something like a multi-step form, you would need to use v-if
on your providers to toggle the visibility of your steps. However, when the provider is hidden and shown again, it does not keep its state.
You can use the persist
prop to allow the provider to remember its state across mounting/destroyed lifecycles, but there are a couple of caveats:
- Your Provider must be inside an observer component.
- Your Provider must have a
vid
property set.
# Adding Errors Manually
You may want to add manual errors to a field, such cases like pre-filling initially due to a server response, or an async request. You can do this using refs
and the applyResult
method.
TIP
If you are using TypeScript you may face issues with $refs
not giving you the correct typings, you can solve that by casting the ref to a ValidationProvider
.
# Nested Slots
If you want to validate a field inside another component that uses slots, you need to be aware that the ValidationProvider
only detects inputs marked by v-model
that are within its immediate slot, meaning nested inputs inside other components will not be detected.
For example, this will not be detected.
One way around that is to invert the nesting of the components, for example the above example should be functionally and visually equivalent to this:
But we have placed the input inside the provider slot directly and it should be detected and validated correctly, you can also use the slim
prop to make sure everything stays visually the same.
# Reference
Below is the reference of the ValidationProvider public API.
# Props
All the following props are optional.
Prop | Type | Default Value | Description |
---|---|---|---|
rules | string object | undefined | The validation rules. |
vid | string | auto increment number | Identifier used for target/cross-field based rules. |
immediate | boolean | false | If the field should be validated immediately after render (initially). |
events | string[] | ['input'] | deprecated: check interaction modes |
name | string | undefined | A string that will be used to replace {field} in error messages and for custom error messages. |
bails | boolean | true | If true, the validation will stop on the first failing rule. |
debounce | number | 0 | Debounces the validation for the specified amount of milliseconds. |
tag | string | span | The default tag to render. |
persist | boolean | false | If true, the provider will keep its errors across mounted/destroyed lifecycles |
slim | boolean | false | If true, it will make the provider renderless, only rendering the HTML inside its slot. |
# Methods
Those are the only methods meant for public usage, other methods that may exist on the ValidationProvider are strictly internal.
Method | Args | Return Value | Description |
---|---|---|---|
validate | value?: any | Promise<ValidationResult> | Runs a validation of the current value against the rules defined. If a value is provided, it is used as the current value and validates it. |
validateSilent | void | Promise<ValidationResult> | Runs a validation of the current value against the rules defined. does not mutate the validation state. |
applyResult | ValidationResult | void | Takes a validation result object and applies it on the current state. |
reset | void | void | Resets validation state. |
setFlags | Object | void | Updates the field flag states with an object, the object properties should be the flag names and the values should be boolean values. |
# Events
The validation provider does not emit any events at this time.
The ValidationProvider
component is a regular component that wraps your inputs and provides validation state using scoped slots.
TIP
The slots syntax has been changed in Vue 2.6, the following examples use the new v-slot
syntax instead of the deprecated slot-scope
, but it is still supported and you can use it. However v-slot
have different semantics, consult the Vue docs for more information.
Using the ValidationProvider offers isolated scope for each field validation state, and does not inject/mutate anything outside its slot. You can import it and use whenever you need it. Using the validation context will allow you to apply classes, flags and pass state to your template.
Here is a quick example:
It also works for custom components and solves the issue of authoring self validated components, which is hard to achieve normally because of the directive limitations.
TIP
The fields being validated must have a v-model
so the component can correctly identify the element/component being validated unless the field accepts a file.
# Rendering
By default, ValidationProvider renders a span
, Consider the following example:
The default tag can be changed using the provider's tag
prop.
# Renderless
Sometimes it is unsuitable for a Provider component in principle to render anything extra, because of limitations in the Vue rendering engine we cannot have multiple root nodes which limits the design choice to move away from renderless at the moment, in Vue 3.x it this may change with fragments.
In 2.2.10 a slim
prop can be used to force the component to be renderless, by default it is set to false
.
Note that only the first child will be rendered when slim
is used, any other nodes will be dropped as you cannot have multiple root nodes in a renderless component. Be mindful of that when using the slim
prop.
# Scoped Slot Data
The object passed down to the slot scope is called the validation context. It has the following properties:
Name | Type | Description |
---|---|---|
errors | string[] | The list of error messages. |
failedRules | [x: string]: string | A map object of failed rules with (rule, message) as a (key, value) |
valid | boolean null | The current validation state. |
flags | { [x: string]: boolean } | The flags map object state. |
aria | { [x: string]: string } | Map object of aria attributes for accessibility. |
classes | { [x: string]: boolean } | Map object of the classes configured based on the validation state. |
validate | (e: any) => Promise | A function that is used as an event handler to trigger validation. Useful for fields that do not use v-model. |
reset | () => void | A function that resets the validation state on the provider. |
Since slot scopes can take advantage of ES6 destructing, you can opt-in for any of those properties and pass down to your slot template as you see fit. The example above only needed the errors
array.
# Examples
The previous quick sample validates simple HTML inputs, lets take this up a notch and validate popular 3rd party components like Vuetify's TextInput.
# Basic Example
This passes error messages down to Vuetify's text field component.
# Manual Validation
Triggering validation on any of the providers is simple, but it is opt-in. Meaning you need to explicitly call the validation on the provider instance. Using refs and the public methodvalidate
makes it straight forward.
If you only plan to trigger manual validation using the UI, you can use the validate
handler on the v-slot data to trigger validation without having to use refs
.
Note that the validate
method on the validation handler, you can use the $event
in the Vue template to reference the event arg that is emitted with the event if your handlers are more complex.
# Validation Result
The validate
method returns a validation result wrapped in a promise, so normally you either would use then
or await
for the validation to finish. The validation result contains useful information about the validation attempt:
TIP
Using the same approach you can reset validation state for the provider using the public method reset()
and the slot scope method of the same name.
# File Validation
While v-model
is generally required when using the ValidationProvider component, some inputs like file
do not benefit from having v-model
. Instead, you can use the manual validate
method to avoid having to use v-model
in this instance.
# Input Groups (Checkbox/Radio)
Like radio inputs and (sometimes) checkboxes, some inputs behave as a single input entity. You can wrap a whole group of inputs given that they have the same v-model
in a single ValidationProvider component. You can group as many inputs as you want inside the ValidationProvider component.
Slot Scope Props Vue Download
# Cross-Field Validation
When using the directive, the confirmed
rule targets the other field that has a corresponding ref
. Using the ValidationProvider is slightly different; it looks for a ValidationProvider component that has a matching vid
prop. The vid
can be either a number or a string.
# Refactoring Validation Providers
While the ValidationProvider has its advantages, it is more verbose than using the v-model
directive, and can be very annoying when creating large forms. There are a couple of ways to address this issue.
# Creating Higher-Order Components
A common pattern in React is to use higher-order components to produce new components with slightly different behavior. This is similar to creating a wrapper or a mixin for our component, except it uses props/events to communicate state.
The withValidation
method takes a component as an argument and creates a new one with the validation behavior enabled. Let's create a VTextFieldWithValidation
using this method:
TIP
Note that the second parameter is a function that transforms the validation context to props object to be passed to the wrapped component. In this case we want to pass the errors
array as the error-messages
prop to the VTextField
component.
With this approach the last example becomes:
WARNING
This approach has some cons, for example if the wrapped component accepts props that have the same name as the ValidationProvider
component. while it will receive these props, they may be of different types, which could lead to serious issues. The problem with HOCs are that you need to be aware of the underlying component's implementation. This can be problematic when working with 3rd party components.
# Wrapping Components Manually
Instead we can wrap the field component with the ValidationProvider in a new component. This is easier and more flexible, and avoids some of the potential problems with Higher-Order components.
Consider this new VTextFieldWithValidation
component.
Ideally you would pass the props you need to either the ValidationProvider
or the VTextField
being validated, with this approach solves the verbosity problem while preserving the simple scoped slots API. It also allows you to distribute props without the issues of having a conflict, unlike HOC.
Using either of these approaches is at your preference.
# Persisting Provider Errors
Sometimes when building something like a multi-step form, you would need to use v-if
on your providers to toggle the visibility of your steps. However, when the provider is hidden and shown again, it does not keep its state.
You can use the persist
prop to allow the provider to remember its state across mounting/destroyed lifecycles, but there are a couple of caveats:
Slot-scope= Props Vuetify
- Your Provider must be inside an observer component.
- Your Provider must have a
vid
property set.
# Adding Errors Manually
You may want to add manual errors to a field, such cases like pre-filling initially due to a server response, or an async request. You can do this using refs
and the applyResult
method.
TIP
If you are using TypeScript you may face issues with $refs
not giving you the correct typings, you can solve that by casting the ref to a ValidationProvider
.
# Nested Slots
If you want to validate a field inside another component that uses slots, you need to be aware that the ValidationProvider
only detects inputs marked by v-model
that are within its immediate slot, meaning nested inputs inside other components will not be detected.
For example, this will not be detected.
Vue Slot-scope Props Not Defined
One way around that is to invert the nesting of the components, for example the above example should be functionally and visually equivalent to this:
But we have placed the input inside the provider slot directly and it should be detected and validated correctly, you can also use the slim
prop to make sure everything stays visually the same.
# Reference
Below is the reference of the ValidationProvider public API.
# Props
All the following props are optional.
Prop | Type | Default Value | Description |
---|---|---|---|
rules | string object | undefined | The validation rules. |
vid | string | auto increment number | Identifier used for target/cross-field based rules. |
immediate | boolean | false | If the field should be validated immediately after render (initially). |
events | string[] | ['input'] | deprecated: check interaction modes |
name | string | undefined | A string that will be used to replace {field} in error messages and for custom error messages. |
bails | boolean | true | If true, the validation will stop on the first failing rule. |
debounce | number | 0 | Debounces the validation for the specified amount of milliseconds. |
tag | string | span | The default tag to render. |
persist | boolean | false | If true, the provider will keep its errors across mounted/destroyed lifecycles |
slim | boolean | false | If true, it will make the provider renderless, only rendering the HTML inside its slot. |
# Methods
Those are the only methods meant for public usage, other methods that may exist on the ValidationProvider are strictly internal.
Method | Args | Return Value | Description |
---|---|---|---|
validate | value?: any | Promise<ValidationResult> | Runs a validation of the current value against the rules defined. If a value is provided, it is used as the current value and validates it. |
validateSilent | void | Promise<ValidationResult> | Runs a validation of the current value against the rules defined. does not mutate the validation state. |
applyResult | ValidationResult | void | Takes a validation result object and applies it on the current state. |
reset | void | void | Resets validation state. |
setFlags | Object | void | Updates the field flag states with an object, the object properties should be the flag names and the values should be boolean values. |
# Events
Slot Scope Props Vueling
The validation provider does not emit any events at this time.