Conditional v-bind in Vue.js [duplicate] - vue.js

This question already has answers here:
Passing props dynamically to dynamic component in VueJS
(6 answers)
Closed 7 months ago.
Is there a way to put a v-bind:something conditionally?
I have this:
<div class="sample">
<div class="some-stuff" :handle=".handle" />
</div>
I want the :handle bind to be conditionally activated.
Having it duplicated with a v-if like this:
<div class="sample">
<div v-if="condition" class="some-stuff" :handle=".handle"/>
<div v-else class="some-stuff" />
</div>
costs too much performance, as it has to rerender a bunch of stuff inside the .some-stuff div.

Give this a try:
<div class="sample">
<div class="some-stuff" v-bind="{ [condition && 'handle']: '.handle' }" />
</div>
Got idea from:
Passing props dynamically to dynamic component in VueJS
And from docs:
<!-- binding an object of attributes -->
<div v-bind="{ id: someProp, 'other-attr': otherProp }"></div>
https://vuejs.org/api/built-in-directives.html#v-bind

Related

Using a component inside another component in VueJS

While I was reviewing headlessui's menu component, I saw the use of 2 components that are nested like the following: (see: https://headlessui.dev/vue/menu)
<template>
<Menu>
<MenuButton>More</MenuButton>
<MenuItems>
<MenuItem v-slot="{ active }">
// some content
</MenuItem>
</MenuItems>
</Menue>
</template>
So as you may see, there is a MenuItem component inside of the MenuItems component. And I need something similar to that so I can use a template and put another component's result into that template.
Here the example of what I am trying to do:
<!-- HeadingComponent.vue -->
<div class="group">
<div class="head">
{{ title }} <button>Create New</button>
</div>
<div class="content">
<!-- I want to put some component's rendered content here -->
</div>
</div>
And this is, let's say, a page where I want to use the common component.
<!-- Blog.vue -->
<HeadingComponent :title="Posts">
<BlogPostsComponent :post="someArray"/> <!-- Some other component which may vary -->
</HeadingComponent>
The question
What kind of changes do I need to do in the component HeadingComponent.vue so it works as I expected?
Slots are a good way to add a component to another or even simple html
docs : https://fr.vuejs.org/v2/guide/components-slots.html
<h1>Vue JS Slots Application</h1>
<div id="app">
<slots>
<template slot="slotA"><pre>Slot A Content from parent.</pre></template>
<template><i>Parent Component Content.</i></template>
</slots>
<hr/>
<slots>
<template slot="slotB">Replace Slot B Default Content</template>
<template><b>Replace Default Slot Content.</b></template>
</slots>
</div>
<template id="aside">
<div>
<h3>My Slots App</h3>
<slot>Default Slot Content</slot><br>
<slot name="slotA"></slot><br>
<slot name="slotB"></slot><br>
</div>
</template>
Example of codepen :
https://codepen.io/brian_kim/pen/NpWKGe
Just in a short time, I found something like slots in VueJS which is definitely what I was looking for.
Here is the guide page:
https://v2.vuejs.org/v2/guide/components-slots
What I did in my problem is that I put <slot></slot> tags inside div whose class is content, and then the last sample I gave (Blog.vue) has worked.
<!-- HeadingComponent.vue -->
<div class="group">
<div class="head">
{{ title }} <button>Create New</button>
</div>
<div class="content">
<!-- I want to put some component's rendered content here -->
<slot></slot>
</div>
</div>

Vue refs undefined in modal

I do have a for loop and inside i want to have a modal for each image
<div class="col pb-3" v-for="(item, index ) in img" :key="index" style="width: 300px;height:auto;">
<img v-b-modal="'modal-'+index" :ref="'image'" #mouseover="mouseOver" #mouseleave="mouseOut" /><br>
<b-modal :id="'modal-'+index" title="BootstrapVue">
<p class="my-4">Hello from modal - {{index}}</p>
<img :ref="'imagex'" />
</b-modal>
<div class="progress pt-2 mt-1" style="width: 100px;margin: 0 auto;">
<div class="progress-bar " :style="[{'width':width[index]+'px'}]" role="progressbar"
aria-valuenow="0" ref="'progress'" aria-valuemin="0" aria-valuemax="100"></div>
</div>
</div>
In methods i am giving src value to each image that has :ref="'image'" and i can actually give a src to them its work fine but, i also want be able to give src value images in modal. Its called :ref="'imagex'" but its undefined.
this.$refs.image[i].src = event.target.result //works
this.$refs.imagex[i].src = event.target.result //undefined
What is the problem an is there anyway to solve it ?
When used on elements/components with v-for, the registered reference will be an Array containing DOM nodes or component instances.
An important note about the ref registration timing: because the refs themselves are created as a result of the render function, you cannot access them on the initial render - they don’t exist yet! $refs is also non-reactive, therefore you should not attempt to use it in templates for data-binding.
.
can use it in events and only at mounted function.
https://v2.vuejs.org/v2/api/#ref

How can I load different components in the same page

Each user type in my app needs to have a different dashboard, so, at the moment, my admin vue looks like the following:
<template>
<main id="admin-main">
<header id="admin-dashboard-header" class="jumbotron">
<div>
<h1>Job Dashboard</h1>
<p>Worker > Dashboard</p>
</div>
</header>
<div class="row container">
<div class="col-4">
<ul class="list-group text-center">
<li class="list-group-item active">Dashboard</li>
<li class="list-group-item">Companies</li>
<li class="list-group-item">Jobs</li>
<li class="list-group-item">Candidates</li>
</ul>
</div>
<div class="col-8">
All components must load here
</div>
</div>
</main>
</template>
<style scoped>
h1{
font-size: 50px;
}
</style>
Ideally, each list item(Companies, Jobs, Candidates) must load their respective component.
So, for instance, how can I load jobs component in this same page when I click on the jobs list item?
One solution would be to use dynamic components. See: https://v2.vuejs.org/v2/guide/components.html#Dynamic-Components
You can see an example I made here: https://codepen.io/bergur/pen/bPEJdB
In my Vue app I've made a data property called selectedComponent, and defined a method that sets that property according to the parameter
setComponent(name) {
this.selectedComponent = name
}
You then invoke that function with something like:
<button #click="setComponent('menuList')">Menu List</button>
And here is the real magic
<component :is="selectedComponent" />
So when I press the button. The data property selectedComponent gets the value menuList which is the registered component.
The component tag then renders that component.

vuejs component that inherits parent's context

Let's start from this
<div class="form-group" :class="{'has-error':determineError('content')}">
<label>Content Label</label>
<div class="mandat">*</div>
<input v-model="form.content" name="content" v-validate="'required|min:5|max:100'" class="form-control">
</div>
The first thing I would like to obtain is to put this piece of code somehow inside a component, something like this:
Vue.component('form-group', {
...
template: `<div class="form-group" :class="{'has-error':determineError('content')}">
<label>Content Label</label>
<div class="mandat">*</div>
<input v-model="form.content" name="content" v-validate="'required|min:5|max:100'" class="form-control">
</div>`
});
As you can see I still have the input field right there. What I would like to do is pass any piece of code instead and the current component must inherit parent's context.
Something like
<form-group>
<template>
<input v-model="form.content" name="content" v-validate="'required|min:5|max:100'" class="form-control">
</template>
</form-group>
How can this be achieved? Notice that I still use parent's context. If using parent's context is not possible, then how can I achieve this in the simplest way?
You have to use slots, which are expanded in the component template with the contents passed by the parent.
In the form-group component:
<template>
<div class="form-group" :class="{'has-error':determineError('content')}">
<label>Content Label</label>
<div class="mandat">*</div>
<slot v-bind:form="form"></slot>
</div>
</template>
You can also add a fallback content inside the <slot> (a default input maybe). Note we are passing the context for the slot contents (see Scoped Slots).

Aurelia nested repeat.for context of parent repeat.for

When nesting repeat.for in Aurelia, an internal repeat.for does not have access to the variable used in it's parent repeat.for.
Example
<div repeat.for="x of 8">
<div repeat.for="y of 8">
${x} - ${y}
</div>
</div>
In the above example, ${x} does not emit anything. How do you get the x value when inside the internal repeat.for?
Found my answer. You need to do the following:
<div repeat.for="x of 8">
<div repeat.for="y of 8">
${$parent.x} - ${y}
</div>
</div>