Vue.js attribute binding from a list or object - vuejs2

I'm experimenting with Vue.js (2.3). I'm comfortable with attribute binding manually e.g.
Vue.component('my-component', {
props: ['info'],
computed: {
type: function() { return info.type },
classList: function() { return this.info.attributes.classList },
id: function() { return this.info.attributes.id }
}
template: '<component :is="type" :class="classList" :id="id">{{ info.text }}</component>'
})
where info =
{
text: 'Some text',
type: 'h2',
attributes: {
classList: 'a string',
id: 'another-string'
}
}
This would output the following:
<h2 class="a string" id="another-string">Some text</h2>
But what if I want to bind all the attributes inside my attributes object, regardless of how many or what they are e.g. my info might look like this:
{
text: 'Some text',
type: 'td'
attributes: {
classList: 'a string',
id: 'another-string',
colspan: '3',
rowspan: '2',
title: 'A string',
...
}
}
How can I bind all these attributes without having to list all the possible attributes that might crop up?

v-bind accepts an object as it's parameter and binds all the properties to their values.
template: '<component :is="type" v-bind="info.attributes"></component>'

Related

Dropdown down item required

Hello I have a dropdown.
I need to make sure an option is selected, thus I want to make a client validation for required field.
<b-dropdown id="clientData"
name="clientData"
v-model="$v.clientData.selectedOption.$model"
:text="clientData.selectedOption"
class="m-2 col-2" no-flip>
<b-dropdown-item v-for="option in clientData.options"
:key="option.value"
:value="option.value"
#click="clientData.selectedOption = option.value">
{{option.text}}
</b-dropdown-item>
</b-dropdown>
<script>
import { required } from 'vuelidate/lib/validators'
const selectedOptionCheck = (selectedOption) => selectedOption !== 'Choose data type'
data () {
return {
clientData: {
csvFile: null,
selectedOption: 'Choose data type',
options: [
{
value: 'PhoneNumber',
text: 'Phone Number'
},
{
value: 'Email',
text: 'Email'
},
{
value: 'DeviceToken',
text: 'Device Token'
}
]
}
}
},
validations: {
clientData: {
selectedOption: {
required,
selectedOptionCheck
}
}
},
</script>
This is because I do not want to send incorrect request to the server.
I have used Vuelidate and it does not work. I have tried searching for a required tag and I have tried aria-required='Please choose an option' on the b-dropdown, however, again it does not work.
You can do following - set your v-model in your data return equal null.
Than try to use computed and check if something is selected like this:
computed: {
validData: function () {
return this.yourvmodelname
},
}

Data not being passed from Child Data to Parent Props

I have a Request Form Component, and within this request form Component I have a Dropdown Menu Component, which I will link both below. All values in my table are pushed into an object upon hitting the Submit Button. However my dropdown selection is only being picked up by my console.log and not being pushed into the Object.
I'm not so familiar with Vue, so I'm not sure what direction to go in for fixing this. I'll attach the relevant (?) pieces of code below.
Parent Component:
<SelectComponent :selected="this.selected" #change="updateSelectedValue" />
export default {
fullScreen: true,
name: 'CcRequestForm',
mixins: [BaseForm],
name: "App",
components: {
SelectComponent,
},
data() {
return {
selected: "A",
};
},
props: {
modelName: {
default: 'CcRequest',
},
parentId: {
type: Number,
default: null,
},
},
mounted() {
this.formFields.requester.value = this.currentRequesterSlug;
},
destroyed() {
if (!this.modelId) return;
let request = this.currentCcRequest;
request.params = request.params.filter(p => p.id)
},
computed: {
...mapGetters(['ccTypesForRequests', 'currentRequesterSlug', 'currentCcRequest']),
ccTypesCollection() {
return this.ccTypesForRequests.map((x)=>[x.slug, this.t(`cc_types.${x.slug}`)]);
}
},
methods: {
addParam() {
this.addFormFields(['params'], {
slug: '',
name: '',
isRequired: true,
description: '',
typeSlug: '',
selected: ''
});
},
deleteParam(idx){
this.removeFormFields(['params', idx]);
},
restoreParam(idx){
this.restoreFormFields(['params', idx])
},
$newObject() {
return {
slug: '',
name: '',
isAbstract: false,
requester: '',
description: '',
status: 'inactive',
params: [],
selected: ''
};
},
$extraPrams() {
return {
parentId: this.parentId,
};
},
updateSelectedValue: function (newValue) {
this.selected = newValue;
},
},
watch: {
selected: function (val) {
console.log("value changed", val);
},
},
};
Child Component:
<script>
export default {
name: "SelectComponent",
props: {
selected: String,
},
computed: {
mutableItem: {
get: function () {
return this.selected;
},
set: function (newValue) {
this.$emit("change", newValue);
},
},
},
};
You have to define the emit property in the parent component, or else it won't know what to expect. That would look like:
<SelectComponent :selected="this.selected" #update-selected-value="updateSelectedValue" />
Check out this tutorial for more information: https://www.telerik.com/blogs/how-to-emit-data-in-vue-beyond-the-vuejs-documentation
To update selected property inside the object, in this constellation, you need to update object property manually upon receiving an event, inside of updateSelectedValue method. Other way could be creating a computed property, since it's reactive, wrapping "selected" property.
computed: {
selectedValue () {
return this.selected
}
}
And inside of object, use selectedValue instead of selected:
return {
...
selected: selectedValue
}

Data variable undefined from computed Vue

I think im not understanding something properly or is an obvious oversight but I cant access values returned from my data() function in my Vue component's computed properties. From my below code i am trying to return a computed property newmessage but it is saying that message is undefined and so is everything else in data if i try. Appreciate any help :)
<script>
export default {
props:['alertdata'],
data () {
return {
message: 'hello',
expanded: [],
singleExpand: false,
alertHeaders: [
{
text: 'Rule Number',
align: 'start',
sortable: false,
value: 'RuleNumber',
},
{ text: 'Date', value: 'DateCreated' },
{ text: 'Amount', value: 'Amount' },
],
alerts: this.alertdata,
transactions : this.alertdata.detail,
}
},
computed: {
newmessage : function() {
return message.reverse()
}
}
}
</script>
Typically, inside methods, or computed properties or lifecycle handlers in Vue, you will use this to refer the component to which the method/computed/handler is attached. this refers to the context in which the function is currently executing.
in your case you need to add this before message
computed: {
newmessage : function() {
return this.message.reverse()
}
You need to refer to property defined in data with this keyword:
newmessage : function() {
return this.message.reverse()
}

Vee validate return true, but should return false

Im using Vuetify, and have a form where im using VeeValidate for form validation...
When im using this:
this.$validator.validateAll().then((result) => {
console.log("result form", result);
//result ? this.onSubmit() : scrollTo(0, 250);
});
It always returns true, even if the validation on my input field isn't valid...
The input looks like:
<v-textarea
filled
name="string"
:label="placeholderText"
auto-grow
single-line
:placeholder="placeholderText"
v-model="answer"
:required="isRequired"
v-validate:computedProp="checkRequired"
:error-messages="errors.collect('string')"
data-vv-name="string"
:hint="hintText"
#blur="updateAnswer"
></v-textarea>
The code for the input component:
export default {
$_veeValidate: {
validator: 'new'
},
name: 'String',
props: {
placeholderText: {
default: 'Add a value'
},
hintText: {
default: 'Add a value'
},
isRequired: {
default: true
}
},
data: () => ({
answer: ''
}),
computed: {
checkRequired() {
return this.isRequired ? 'required' : ''
}
},
methods: {
updateAnswer() {
this.$validator.validateAll();
this.$emit('updateAnswer', this.answer);
}
}
}
Im calling this.$validator.validateAll() in another component... The input component is a standalone component... I have it all wrappet in a form tag, and running the validate function on a submit
You have two choice:
Pass to the component the v-validate from the $attrs
Inject the $validator to the component
Parent
export default {
name: "App",
components: {
YourComponent
},
provide() {
return {
$validator: this.$validator
};
},
Child
$_veeValidate: {
validator: "new"
},
inject: ["$validator"],
name: "String",
You can also simplify your html code, see the VeeValidate Syntax
Html
v-validate="{ required: this.isRequired }"
And you can safely remove
:required="isRequired"

Preview a reference

I want to preview a reference name in the studio
I have and icon type, for example one which has the title 'facebook'
export default {
name: 'icon',
title: 'Icon',
type: 'document',
fields: [
{
name: 'name',
title: 'Name',
type: 'string'
},
]
}
I reference this in a menu elsewhere like this
{
name: 'icon',
title: 'Icon',
type: 'reference',
to: [{ type: 'icon' }]
},
and then try to preview like this
preview: {
select: {
title: 'icon',
},
prepare(selection) {
const { title } = selection;
return {
title: title.name,
}
}
}
but my selection returns the reference object, with _ref etc. not the object itself. Is there a way to preview this reference?
You can dot your way into the property on the reference that you'd like to use in the preview like this:
preview: {
select: {
title: 'icon.name',
},
prepare(selection) {
const { title } = selection;
return {
title: title.name,
}
}
}
Side note: Since the prepare function now just passes through its input, you can remove it altogether. This would be sufficient:
preview: {
select: {
title: 'icon.name'
}
}