Vue 3 Interference between component - vuejs3

I've an issue on vue3 component.
I'm calling the same component two times "pillCheck"
when clicking on the second it change the first
<pillCheck :key="1">
<template v-slot:spanFalse> Metric </template>
<template v-slot:spanTrue> Imperial </template>
</pillCheck>
<pillCheck :key="2">
<template v-slot:spanFalse> Pierre </template>
<template v-slot:spanTrue> Camille </template>
</pillCheck>
and the component is as follow :
<template lang="html">
<div class="pill">
<input
id="checkbox"
#change="changeValue($event)"
type="checkbox"
class="switch-checkbox"
/>
<label for="checkbox" class="switch-label">
<span><slot name="spanFalse"></slot></span>
<span><slot name="spanTrue"></slot></span>
<div
class="switch-toggle"
:class="{ 'switch-toggle-checked': isTrue }"
></div>
</label>
</div>
</template>
<script setup>
import { ref } from "vue";
const isTrue = ref(false);
function changeValue(evt) {
console.log(evt);
isTrue.value = !isTrue.value;
}
</script>
Thanks for your help

Related

How to replace the .native in Vue3?

<component :is="item.component"
:index="i"
v-on:drop="onDrop(e,i)"
/>
--component--
<template>
<div>hello world</div>
</template>
<script>
export default {
emits:['drop']
}
i'm trying to do something like vue3 doc said,but does not work.
update:
these code work
<template>
<div
#drop.stop="(e)=>$emit('onDrop',e)"
>hello world</div>
</template>
<component :is="item.component"
#onDrop="onDrop($event,i)"
/>
but if the component is another component instead a div. in this case failed.
<template>
<v-chart
#drop="(e)=>$emit('onDrop',e)"
class="chart" :option="option" autoresize />
</template>
<component :is="item.component"
#onDrop="onDrop($event,i)"
/>

Passing a function as props in Next.js

I am attempting to pass the function submitForm from formControl to index.js (Home). My goal: to remove form, upon successful form submission and show a success message. I have looked at several examples, but I am still missing something.
I am using Next.js, but I don't think the Next.js usage would be any different from react.js in this case. Also using react-hook-form, once again, I don't think RHF is interrupting the process.
index.js Home view
import { useState } from 'react';
import { useForm } from "react-hook-form";
import styles from '../styles/Home.module.css'
import { proteinArr, starchArr, greensArr} from '../utils'
import date from 'date-and-time';
export default function Home({ submitForm }) {
const { register, handleSubmit, control, formState: { errors } } = useForm();
const onSubmit = (data, e) => {
e.target.reset()
submitForm()
}
const now = new Date();
let day = date.format(now, 'dddd').toLowerCase();
// console.log(SaturdayArr)
// console.log(date.format(now, 'dddd').toLowerCase())
return (
<>
<form onSubmit={handleSubmit((onSubmit))}>
<div className={`${styles.home_card} card home_card `}>
<div className="card-body">
<h2 className={styles.title}>Pick your plate!</h2>
<div className={`${styles.home_selectGroup} input-group mb-3`}>
<div className="input-group-prepend">
<span className="input-group-text" >Name</span>
</div>
<input type="text" className="form-control" {...register("name", { required: true })} placeholder="Order Name" aria-label="Order Name" aria-describedby="basic-addon" />
{errors.name && <p>Order name is required</p>}
</div>
<div className={`${styles.home_selectGroup} input-group mb-3`}>
<div className="input-group-prepend">
<span className="input-group-text" >Email</span>
</div>
<input type="email" id="email" className="form-control" {...register("email")} placeholder="Email#provider.com" aria-label="Email" aria-describedby="basic-addon" />
</div>
<div className={`${styles.home_selectGroup} input-group mb-3`}>
<div className="input-group-prepend">
<span className="input-group-text" >Phone Number</span>
</div>
<input type="tel" id="phone" className="form-control" {...register("phone", { required: true })} placeholder="111-111-1111" aria-label="Phone Number" aria-describedby="basic-addon" />
{errors.name && <p>Phone number is required</p>}
</div>
<div className={`${styles.home_selectGroup} input-group mb-3`}>
<div className="input-group-prepend">
<label className={`${styles.homeLabel} input-group-text`} htmlFor="inputGroupSelect01">Protein</label>
</div>
<select {...register("protein", { required: true })}
className={`${styles.home_select} custom-select" id="inputGroupSelect01`}
>
<option className={styles.home_option}>Choose...</option>
{proteinArr && proteinArr.map((item) => <option key={item}>{item}</option>)}
</select>
{errors.protein && <p>Protein is required</p>}
</div>
<div className={`${styles.home_selectGroup} input-group mb-3`}>
<div className="input-group-prepend">
<label className={`${styles.homeLabel} input-group-text`} htmlFor="inputGroupSelect01">Greens</label>
</div>
<select
{...register("greens", { required: 'select an option' })}
className={`${styles.home_select} custom-select" id="inputGroupSelect01`}>
<option className={styles.home_option}>Choose...</option>
{greensArr && greensArr.map((item) => <option key={item}>{item}</option>)}
</select>
{errors.greens && <p>Green is required</p>}
</div>
<div className={`${styles.home_selectGroup} input-group mb-3`}>
<div className="input-group-prepend">
<label className={`${styles.homeLabel} input-group-text`} htmlFor="inputGroupSelect01">Starch</label>
</div>
<select {...register("starch", { required: true })} className={`${styles.home_select} custom-select" id="inputGroupSelect01`}>
<option className={styles.home_option}>Choose...</option>
{starchArr && starchArr.map((item) => <option key={item}>{item}</option>)}
</select>
{errors.starch && <p>Starch is required</p>}
</div>
<button className="btn btn-primary contact-form_button " type="submit">Submit My Order</button>
</div>
</div>
</form>
</>
)
}
FormControl
import Home from '../../pages/index'
import { useState } from 'react';
const FormControl = () => {
const [isSubmitted, setIsSubmitted] = useState(false);
function submitForm(){
setIsSubmitted(true);
}
return (
<div>
{isSubmitted == false ? <Home submitForm={submitForm}/> : <h2>Your from was submitted</h2>}
</div>
);
}
export default FormControl;
Next.js is just logic on top of React so the way you interact with it is handled the same for both libraries.
However, pages in React and Next.js are both components but pages in Next.js have a lot of functionality added/injected, so you must treat them differently.
Because of this, you cannot just pass props to pages in Next.js like you are as they will always be undefined. You can set page props via getInitialProps, getStaticProps, getServerSideProps, in _document, or even in _app.
With that said, you can simplify your form status by using react-hook-form's successful form submission status.
export default function Home() {
const {formState: { isSubmitSuccessful } } = useForm();
if(isSubmitSuccessful) return <h2>Your from was submitted</h2>;
<form onSubmit={handleSubmit((onSubmit))}>
...form stuff
</form>
}
You could make the form it's own component too
Home page
import HomeForm form './HomeForm'
export default function Home() {
handleSubmit= () => {...submit logic}
return <HomeForm onSubmit={handleSubmit} />
}
Home form component
export default function HomeForm({ onSubmit }) {
const {formState: { isSubmitSuccessful } } = useForm();
if(isSubmitSuccessful) return <h2>Your from was submitted</h2>;
<form onSubmit={handleSubmit((onSubmit))}>
...form stuff
</form>
}

How can I make button minus and plus on the bootstrap vue?

I get tutorial from here : https://bootstrap-vue.js.org/docs/components/form-input
I want to make like this :
I try like this :
<template>
...
<b-col class="pr-0 custom-control-inline">
<b-btn variant="warning btn-sm mr-1 mt-1 mb-1"><i class="fa fa-minus-circle"></i></b-btn>
<b-form-input type="number" class="col-md-3" v-model="quantity"></b-form-input>
<b-btn variant="info btn-sm ml-1 mt-1 mb-1"><i class="fa fa-plus-circle"></i></b-btn>
</b-col>
...
</template>
<script>
export default {
data () {
return {
quantity: null
}
}
}
</script>
The result like this :
How can I make button plus and minus works?
So if click button plus, the quantity go up
From the docs:
<b-input-group>
<b-input-group-prepend>
<b-btn variant="outline-info">-</b-btn>
</b-input-group-prepend>
<b-form-input type="number" min="0.00"></b-form-input>
<b-input-group-append>
<b-btn variant="outline-secondary">+</b-btn>
</b-input-group-append>
</b-input-group>
Just style the buttons as you like and add click event to the buttons for the input number logic, like:
new Vue({
el: '#app',
data: {
num: 0
}
})
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue.css" />
<!-- Add this after vue.js -->
<script src="https://unpkg.com/vue"></script>
<script src="//unpkg.com/babel-polyfill#latest/dist/polyfill.min.js"></script>
<script src="//unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue.js"></script>
<div id="app">
<b-input-group>
<b-input-group-prepend>
<b-btn variant="outline-info" #click="num--">-</b-btn>
</b-input-group-prepend>
<b-form-input type="number" min="0.00" v-model="num"></b-form-input>
<b-input-group-append>
<b-btn variant="outline-secondary" #click="num++">+</b-btn>
</b-input-group-append>
</b-input-group>
</div>
Maybe like this:
<template>
<div class="quantity">
<b-input-group>
<b-input-group-prepend>
<b-btn variant="info" #click="decrement()">-</b-btn>
</b-input-group-prepend>
<b-form-input type="number" min="0.00" :value="quantity"></b-form-input>
<b-input-group-append>
<b-btn variant="info" #click="increment()">+</b-btn>
</b-input-group-append>
</b-input-group>
</div>
</template>
You can use type="number" or type="text".
And simple logic:
<script>
export default {
name: "Quantity",
data() {
return {
quantity: 1
};
},
methods: {
increment() {
this.quantity++;
},
decrement() {
if (this.quantity === 1) {
alert("Negative quantity not allowed");
} else {
this.quantity--;
}
}
}
};
</script>
Codesandbox example

Meteor collection item id from template

I am loading a series of template from a collection like so.
sidebar/sidebar.html
<template name="Sidebar">
<ul id="slide-out" class="side-nav fixed grey darken-3">
<li class="action-bar">
<span id="add-new" data-target="modal-add" class="modal-trigger"><i class="small material-icons">add</i></span>
<span id="save"><i class="small material-icons">note_add</i></span>
<span id="rename"><i class="small material-icons">mode_edit</i></span>
<span id="delete"><i class="small material-icons">delete</i></span>
<span data-activates="slide-out" id="close" class="button-collapse close "><i class="small material-icons right">reorder</i></span>
</li>
<!-- Load save items-->
{{#if Template.subscriptionsReady}}
{{#each userSaves}}
{{>ListItem}}
{{/each}}
{{else}}
<p>Loading</p>
{{/if}}
</ul>
<i class="material-icons">menu</i>
<!-- Modal form to add new simulator file -->
<!-- Modal Structure -->
<div id="modal-add" class="modal">
<div class="modal-content">
<h4>New Simulator</h4>
{{> quickForm collection=saves id="newSimulator" type="insert" buttonClasses="modal-action modal-close btn waves-effect waves-light" buttonContent="Add"}}
</div>
</div>
</template>
sidebar/Sidebar.js
import { Template } from 'meteor/templating';
import { Saves } from '../../../../api/lists/SimulatorSaves.js';
import { Meteor } from 'meteor/meteor';
import './Sidebar.html';
import './SidebarListItem.js'
Template.Sidebar.onCreated(function() {
var self = this;
self.autorun(() => {
self.subscribe('saves');
})
});
Template.Sidebar.onRendered(function() {
// the "href" attribute of .modal-trigger must specify the modal ID that wants to be triggered
$('.modal-trigger').leanModal({
ending_top: '25%', // Ending top style attribute
});
});
Template.Sidebar.events({
'click .button-collapse': function() {
console.log("here")
$(".button-collapse").sideNav();
}
})
Template.Sidebar.helpers({
saves: () => {
return Saves;
},
userSaves: () => {
return Saves.find({});
}
});
I am trying to get the collection items id from the template so i can use it as a session variable but I am getting undefined.
sidebar/listItem.js
import { Template } from 'meteor/templating';
import { Meteor } from 'meteor/meteor';
import './SidebarListItem.html';
Template.ListItem.events({
'click .file-link': () => {
console.log(this._id);
}
});
sidebar/listitem.html
<template name="ListItem">
<li class="file-link"><i class="material-icons">description</i><span>{{name}}</span></li>
</template>
If any would could help me with this would be great thanks.
You don't have this when using fat arrow ;)

Meteor: Using an HTML Template to add to the DOM.

I'm building an app with Meteor.js, and I've got a form where I would like to be able to allow the user to add a new row to the form when they click a button (button.addExperience). I'm using an HTML Template to populate each row of the form.
How would I have the template (experienceRow) rendered each time the user clicks the button?
See example code below:
<body>
<form>
{{> experienceRow }}
</form>
<button class="addExperience">Add Experience</button>
</body>
<template name="experienceRow">
<div id={{experienceNumber}} class='experienceRow'>
<input type="text" placeholder="name" value="" class="name">
<input type="text" placeholder="address" value="" class="address">
<input type="text" placeholder="phone" value="" class="phone">
</div>
</template>
You will need to use an each block along with a reactive variable. That variable could be a ReactiveVar, a session varaible, a local collection, etc. Here's an example implementation using a ReactiveVar to hold an array of ids:
html
<body>
{{> experienceForm }}
</body>
<template name="experienceForm">
<form>
{{#each experienceIds}}
{{> experienceRow }}
{{/each}}
</form>
<button class="addExperience">Add Experience</button>
</template>
<template name="experienceRow">
<div id={{this}} class='experienceRow'>
<input type="text" placeholder="name" value="" class="name">
<input type="text" placeholder="address" value="" class="address">
<input type="text" placeholder="phone" value="" class="phone">
</div>
</template>
js
Template.experienceForm.onCreated(function() {
this.experienceIds = new ReactiveVar(Random.id());
});
Template.experienceForm.helpers({
experienceIds: function() {
return Template.instance().experienceIds.get();
}
});
Template.experienceForm.events({
'click .addExperience': function(e, template) {
e.preventDefault();
var ids = template.experienceIds.get();
ids.push(Random.id());
template.experienceIds.set(ids);
}
});
Note that you'll need to meteor add reactive-var for this to work.
Recommended reading: scoped reactivity.

Resources