MultiSelect Component for VueJS - vuejs3

I am using the "Multiple Select Component" currently from JQuery. I just found out there is a Vue Version, but it adds a dependency to Jquery I do not like.
https://multiple-select.wenzhixin.net.cn/docs/en/introduction
Is there a native way to do this using VueJS 3.0 or any better replacement?
This is what I am going to achieve:

Yes, you can either create a new component for the dropdown/checkboxes or use a similar component from Vuetify: https://vuetifyjs.com/en/components/selects/#menu-props
For the new component, you could use somethig like this:
<div class="select">
<ul>
<li v-for="(option, index) in options" :key="index">
<input type="checkbox" :id="index" :value="option.value" v-model="selected">
<label :for="index">{{ option.anything }}</label>
</li>
</ul>
</div>
Here's the codepen, I do not own the code.
https://codepen.io/huleos/pen/xQaYdK

Related

How to create a list with actions using materialize-css?

I'm trying to create a list with checkboxes for collecting actions with materialize, but the input tag didn't get recognized by the pattern. Is this possible?
<div class="row">
<ul class="collection with-header" v-if="listaRoles.length > 0">
<li class="collection-header left-align"><h4> Roles do perfil {{ perfil.descricao }}</h4></li>
<li v-for="r in listaRoles" :key="r.id" class="collection-item">
<div class="left-align">
<span> {{ r.descricao }} </span>
<input type="checkbox" />
</div>
</li>
</ul>
</div>
You have to use the exact same structure as the materialize docs, otherwise your components won't work correctly. So in the case of checkboxes that is <input>, followed by <span>, and both of these wrapped in a <label>.
<label>
<input type="checkbox" />
<span>Red</span>
</label>
Any deviation from this will break the component.
EDIT:
Checkboxes inside li works perfectly fine, here a codepen to demonstrate:
https://codepen.io/doughballs/pen/KKpNrPy
The error is coming from somewhere else.
https://materializecss.com/checkboxes.html

Add class to ian:accounts-ui-bootstrap-3 SELECT tag when rendered [Meteor JS + Blaze]

Meteor 1.6.1.1 is the latest version of my project. I am using package ian:accounts-ui-bootstrap-3 instead of accounts-ui. I have added a custom field as <select> in the code.
What I get on Screen is as below.
When I saw the HTML code, it is not adding class="form-control" to select tag.
below is the code when I inspect element on UI using Chrome.
<li id="login-dropdown-list" class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" aria-expanded="false">Sign in / Join <b class="caret"></b></a>
<div class="dropdown-menu">
<div class="select-dropdown">
<label>State</label><br>
<select id="login-state">
</select>
</div>
<button class="btn btn-primary col-xs-12 col-sm-12" id="login-buttons-password" type="button">
Create
</button>
<button id="back-to-login-link" class="btn btn-default col-xs-12 col-sm-12">Cancel</button>
</div>
</li>
All I want is to add class="form-control" to the select tag dynamically when component loads on screen and it must look like below;
I have tried below code, but it is not working;
Template.HomePage.onRendered(function () {
document.getElementById('login-state').classList.add('form-control');
});
Well, I tried one way to achieve this is by using Template event as below,
Template.HomePage.events({
'click #login-dropdown-list': function(event){
//document.getElementById('login-state').classList.add('form-control');
$('#login-state').addClass('form-control');
}
});
As you can see, the component gets loaded inside the li tag with id="login-dropdown-list". I simply loaded the class on click event. Even the commented code works fine.
Is this a good solution? please let me know if there much better answer to this? If it works I will definitely accept and upvote the answer.

Inject data into scope without <template>

I would like to get rid of two lines in the html used in a vue 2.x application. The lines with <template scope="props"> and the corresponding </template> should not be necessary.
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<div id="app">
<p>{{ message }}</p>
<my-component>
<template scope="props">
<p>{{props.test}}</p>
</template>
</my-component>
</div>
I would rather define my own component attribute to define the scope name
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<div id="app">
<p>{{ message }}</p>
<my-component with="props">
<p>{{props.test}}</p>
</my-component>
</div>
So instead of exposing the writer of the HTML to the concepts of templates and scopes we would do that inside my-component.
Does anybody know whether the vue templating mechanism is open for extension inside components like this ?
The benefit of having component is that it can be re-used at multiple places. so idea is to define template at one place and you can use it at multiple places.
the example you have written, you will be able to re-use it at again. template of component is generally not defined inside component, it will be separate and than that component can be used at multiple places.
See one sample below:
<div id="app">
<template id="item-edit">
<li>
<span v-show="!inEdit">{{item.name}}</span>
<input v-show="inEdit" type="text" v-model="item.name" />
{{inEdit ? 'save' : 'edit'}}
</li>
</template>
<ul>
<item-edit v-for="item in items" :item="item"></item-edit>
</ul>
</div>
Complete fiddle: http://jsfiddle.net/corh2tqo/

VueJS component won't render on front end (possibly Drupal issue)

The site I'm currently working on is built in Drupal 7. I have one form that requires user input so I'm attempting to build it with VueJS. The form is contained all within one template file (.tpl.php) and all the content is provided in this template file or via the VueJS Javascript (nothing is coming from the CMS).
The issue I have is that the Vue components are not rendering on the front-end, but when I copy the code into a JSFiddle they do, so I'm guessing it is an issue with the interaction between VueJS and Drupal. Here is a screenshot of my markup when inspecting...
Here is the code from the .tpl.php file...
<div id="app">
<form>
<div>
<label for="year">Per Year</label>
<input type="radio" name="frequency" id="year" value="year" v-model="frequency" checked>
<label for="month">Per Month</label>
<input type="radio" name="frequency" id="month" value="month" v-model="frequency">
</div>
</form>
<ul class="plans">
<template id="plan-component">
<h2 class="plan-name">{{ name }}</h2>
<h2 class="plan-cost">{{ price }}</h2>
<h2 class="plan-tagline">{{ tagline }}</h2>
Choose this plan
</template>
<li>
<plan-component :frequency="frequency"
name="Basic"
tagline="Basic tagline"
price-yearly="Free"
price-monthly="Free"
></plan-component>
</li>
<li>
<plan-component :frequency="frequency"
name="Rec"
tagline="Rec tagline"
price-yearly="3"
price-monthly="4"
></plan-component>
</li>
<li>
<plan-component :frequency="frequency"
name="Team"
tagline="Team tagline"
price-yearly="4"
price-monthly="5"
></plan-component>
</li>
<li>
<plan-component :frequency="frequency"
name="Club"
tagline="Club tagline"
price-yearly="5"
price-monthly="6"
></plan-component>
</li>
</ul>
</div>
..and the code from my JS file...
Vue.component('plan-component', {
template: '#plan-component',
props: ['frequency', 'name', 'tagline', 'priceYearly', 'priceMonthly'],
computed: {
'price': function() {
if (this.frequency === 'year') {
return this.priceYearly;
} else {
return this.priceMonthly;
}
}
},
methods: {
makeActivePlan() {
// We dispatch an event setting this to become the active plan
this.$dispatch('set-active-plan', this);
}
}
});
new Vue({
el: '#app',
data: {
frequency: 'year',
activePlan: {name: 'no', price: 'You must select a plan!' }
},
events: {
'set-active-plan': function(plan) {
this.activePlan = plan;
}
},
});
And here is the JSFiddle which outputs the components correctly - https://jsfiddle.net/2xgrpLm6/
What browser are you using? <template> tags are not supported in IE.
Another idea is to make sure you are never using fragment components (meaning wrap everything inside your template with a div like so:
<template id="foobar">
<div>
CONTENT HERE
</div>
</template>
Lastly, have you turned on Vue debug mode? Before you instantiate your Vue instance, set Vue.config.debug = true and see if you get console errors then.
Try moving the <template id="plan-component">...</template> code outside of the Vue instance. I.e., such that it is not contained within <div id="app">...</div>.
This has solved a similar problem for me in the past, though I'm not sure if it applies here.
For anyone having a similar issue, the solution was simple. After Jeff suggested turning on Vue debug mode (and downloading the Dev version of Vue JS instead of minified - https://vuejs.org/guide/installation.html) the console gave the error [Vue warn]: Cannot find element: #app.
The issue was that Drupal was loading my scripts in the <head>, before <div id="app"> was loaded in the DOM. As such #app couldn't be found. After outputting the scripts before the closing <body> tag all was sorted. See here for more information [Vue warn]: Cannot find element

ngFor with Data binding?

I've got a *ngFor where I fetch a heroes list.
Now, If I change a value of hero, my heroes should be changed too, how do you do it, the best way...
<li *ngFor="#hero of heroes">
<input type="text" [value]="hero.name"/>
</li>
I only know the way to make a (change)="UpdateListByItem(item)" , to call a methode, but isn't there a way to make a two way databind for all items?
You can do two way databinding using ngModel directive
<li *ngFor="#hero of heroes">
<input type="text" [(ngModel)]="hero.name"/>
</li>
Whenever you change the input text the corresponding hero name will get changed.
More information can be found here https://angular.io/docs/ts/latest/guide/forms.html
You could use ngModel to do this automatically
<li *ngFor="#hero of heroes">
<input type="text" [(ngModel)]="hero.name"/>
</li>
Look at this Answer.
ngModel allows to change individual name and update the list immediately.
<ul>
<li *ngFor="#hero of heros">
<input type="type" [value]="hero.name" [(ngModel)]="hero.name" />
</li>
</ul>

Resources