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

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

Related

webcomponent in template and alpine.js

I would like to define a custom element and attach it in a shadow dom. This element use alpine and bootstrap4 and must be graphically isolated from the rest of the dom. Alpine must be included and used directly inside the webcomponent (not in the light dom).
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap#4.4.1/dist/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous" />
<script defer src="//unpkg.com/alpinejs#3.9.3/dist/cdn.min.js"></script>
<div class="container" x-data="my_component">
<div class="row">
<div class="col-lg-2 col-md-4">
<div class="form-group">
<label for="sel1">Sel 1</label>
<select id="sel1" class="form-control" x-model="sel1">
<option value="" disabled>Sel 1</option>
<template x-for="{label, id} in optsSel1" :key="id">
<option
x-text="label"
x-bind:value="id"
x-bind:selected="id === sel1"
></option>
</template>
</select>
</div>
</div>
</div>
<div class="row mt-xs-3 mt-sm-3">
<div class="col-lg-12 text-center">
<button class="btn btn-warning btn-lg btn-block" #click="notify">
Submit
</button>
</div>
</div>
</div>
<script>
const optsSel1 = [{
id: "AF",
label: "Afghanistan"
},
{
id: "AL",
label: "Albania"
},
{
id: "DZ",
label: "Algeria"
}
];
document.addEventListener("alpine:init", () => {
Alpine.data("my_component", () => ({
optsSel1,
sel1: "AF",
notify() {
const data = new URLSearchParams({
sel1: this.sel1
});
alert(data);
}
}));
});
</script>
I tried to wrap the code above in a template tag and define a custom element.
Graphically is ok, bootstrap seems to work.
JS works too indeed on alpine:init an alert is shown.
But all the logic defined in alpine that interact with the dom seems to not working:
select's options are empty;
click on submit button has no effect.
<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div>
<button class="btn btn-warning btn-lg btn-block">button outside</button>
<my-component />
</div>
<template id="my-component_tpl">
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap#4.4.1/dist/css/bootstrap.min.css"
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"
crossorigin="anonymous"
/>
<script defer src="//unpkg.com/alpinejs#3.9.3/dist/cdn.min.js"></script>
<div class="container" x-data="my_component">
<div class="row">
<div class="col-lg-2 col-md-4">
<div class="form-group">
<label for="sel1">Sel 1</label>
<select id="sel1" class="form-control" x-model="sel1">
<option value="" disabled>Sel 1</option>
<template x-for="{label, id} in optsSel1" :key="id">
<option
x-text="label"
x-bind:value="id"
x-bind:selected="id === sel1"
></option>
</template>
</select>
</div>
</div>
</div>
<div class="row mt-xs-3 mt-sm-3">
<div class="col-lg-12 text-center">
<button class="btn btn-warning btn-lg btn-block" #click="notify">
Submit
</button>
</div>
</div>
</div>
<script>
const optsSel1 = [{
id: "AF",
label: "Afghanistan"
},
{
id: "AL",
label: "Albania"
},
{
id: "DZ",
label: "Algeria"
}
];
document.addEventListener("alpine:init", () => {
alert("alpine:init " + JSON.stringify(optsSel1, null, 2));
Alpine.data("my_component", () => ({
optsSel1,
sel1: "AF",
notify() {
const data = new URLSearchParams({
sel1: this.sel1
});
alert(data);
}
}));
});
</script>
</template>
<script>
customElements.define(
"my-component",
class extends HTMLElement {
connectedCallback() {
const shadow = this.attachShadow({
mode: "open"
});
const tpl = document.getElementById("my-component_tpl");
shadow.appendChild(tpl.content);
}
}
);
</script>
</body>
</html>
What'is wrong? Thanks in advance!
You should add
document.addEventListener("alpine:initialized",()=>{
Alpine.initTree(this.shadowRoot)
})
to the connectedCallback function.
Alpine's mutation observer can't see what's inside a shadow dom, so you have to manually initialize it.
See your snippet fixed

Vue Vite Webpack doesn't compile the background image

I'm using VUE Vite and Webpack to compile the files. My problem is the following:
If i set my background image for the body tag in css then I can see the background in the develper verson in the browser. After creating the webpack files it won't use the background.
It seems like it doesnt compile the background. Does anyone know why this issue happens?
I appreciate any kind of help and suggestions.
My Folder structure is the following:
Code:
<template>
<div class="d-flex align-items-center justify-content-center vh-100">
<form>
<div class="mb-3">
<input type="email" class="form-control input-style-1" placeholder="Email eingeben" v-model="email">
</div>
<div class="mb-3">
<input type="password" class="form-control input-style-1" placeholder="Passwort eingeben" v-model="password">
</div>
<div class="d-grid">
<button class="btn btn-primary button-style-1" type="button" #click="login">Einloggen</button>
</div>
<div class="d-grid">
<router-link class="text-white mt-3" to="/register">Neuen Account erstellen</router-link>
</div>
</form>
</div>
</template>
<script>
export default {
name: 'Login',
data: function() {
return {
email: '',
password: ''
}
},
methods: {
async login(){
if(this.email == "" || this.password == "") return;
await window.rpc.callServer("sLoginUser", [this.email, this.password]);
}
}
}
</script>
<style>
body {
background: url("./images/background.jpg") !important;
}
</style>

Why is my react app rendering two input check boxes on mobile? Looks fine on desktop. (See Photos)

Not sure what other info I could supply besides one of the columns that would be helpful. I'm stumped.
[edit] Added full code for this component. This looks fine on desktop but not on my phone or tablet. See the photos. I'm repeating this because I can't save my edits to this question due to having too much code and not enough information so here I am rambling about nothing.
Mobile:
Desktop:
import React, { Component } from 'react';
import API from '../utils/API';
class Attendance extends Component {
state = {
selectedOption: "",
disabled: ""
};
handleOptionChange = (changeEvent) => {
this.setState({
selectedOption: changeEvent.target.value
});
};
handleFormSubmit = (formSubmitEvent) => {
formSubmitEvent.preventDefault();
if (!this.state.selectedOption) {
return;
} else {
this.setState({
disabled: "true"
})
API.updateAttendance(this.props.student._id, { present: this.state.selectedOption });
}
};
render() {
return (
<div className="col d-flex justify-content-end" >
<form onSubmit={this.handleFormSubmit}>
<div className="row mt-3">
<div className="col-sm-3">
<label className="text-danger">
<input
type="checkbox"
value="absent"
checked={this.state.selectedOption === 'absent'}
onChange={this.handleOptionChange}
disabled={this.state.disabled}
/>
Absent
</label>
</div>
<div className="col-sm-3">
<label className="text-warning">
<input
type="checkbox"
value="excused"
checked={this.state.selectedOption === 'excused'}
onChange={this.handleOptionChange}
disabled={this.state.disabled}
/>
Excused
</label>
</div>
<div className="col-sm-3">
<label className="text-success">
<input
type="checkbox"
value="present"
checked={this.state.selectedOption === 'present'}
onChange={this.handleOptionChange}
disabled={this.state.disabled}
/>
Present
</label>
</div>
<div className="col-sm-3">
<div className="form-group">
<button type="submit" className="btn btn-sm btn-dark" onSubmit={this.handleFormSubmit} disabled={this.state.disabled}>
<i className="fas fa-user-check" />
</button>
</div>
</div>
</div>
</form>
</div>
);
}
}
export default Attendance;

trumbowyg editor with vuejs

I am using the trumbowyg editor control in my vuejs spa. From the documentation I know that I can use the following code to set the contents of the editor.
$('#editor').trumbowyg('html','<p>Your content here</p>');
$('#editor').trigger('tbwchange');
However, it is not working for me in my VueJs App. I have an object that has a description key defined. I can console.log the description , but when I try to assign it to the editor control as mentioned above, it fails . I can see no error in the console but the text just won't show up in the editor.
Here is what I am going at the moment.
<template>
<div class="modal fade" data-backdrop="static" data-keyboard="false">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">
<span v-if="anouncement">Edit Anouncement</span>
<span v-else>New Anouncement</span>
</h4>
</div>
<div class="modal-body">
<div class="form-group">
<input type="text" placeholder="enter anouncement summary here" class="form-control" v-model="anouncementObj.summary">
</div>
<div class="form-group">
<input type="text" placeholder="enter location here" class="form-control" v-model="anouncementObj.location">
</div>
<textarea class="note-view__body" id="anonDescription" v-model="description" placeholder="enter event description"></textarea>
</div>
<div class="modal-footer">
<button type="button" v-on:click="clear()" class="btn btn-link" data-dismiss="modal">Close</button>
<button type="button" v-on:click="performSave()" class="btn btn-link">Save</button>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props : {
anouncement : Object
},
data() {
return {
anouncementObj :{}
}
},
mounted () {
this.makeTextBoxReady();
this.anouncementObj = Object.assign({},this.anouncementObj, this.anouncement || {});
$('#anonDescription').trumbowyg('html',this.anouncement.description);
$('#anonDescription').trigger('tbwchange');
console.log(this.anouncement.description);
},
methods : {
makeTextBoxReady: function() {
$(document).ready(function() {
if (!$('html').is('.ie9')) {
if ($('.note-view__body')[0]) {
$('.note-view__body').trumbowyg({
autogrow: true,
btns: [
'btnGrp-semantic', ['formatting'],
'btnGrp-justify',
'btnGrp-lists', ['removeformat']
]
});
}
}
});
},
performSave : function() {
let description = $('#anonDescription').trumbowyg('html');
let formData = new FormData();
for (name in this.anouncementObj) {
formData.append(name, this.anouncementObj[name]);
}
if( !this.anouncementObj.id) {
this.anouncementObj.id = 0;
}
formData.append('description',description);
this.$http.post('/admin/anouncement/createOrUpdate', formData).then(response => {
// console.log(response);
if(response.data.status==200) {
alert(response.data.message);
this.$emit('getAnouncements');
}
})
},
clear: function() {
this.anouncementObj= {};
}
}
}
</script>
Can you please let me know what I am doing wrong here? I have also tried the nexttick approach but even that is not working.
I got it working. I was not using the correct bootstrap modal id. Please see this related question for more information.
This is the correct code.
if(this.anouncementObj && this.anouncementObj.description && this.anouncementObj.id) {
$('#'+this.anouncementObj.id+' #anonDescription').trumbowyg('html',this.anouncementObj.description);
$('#'+this.anouncementObj.id+' #anonDescription').trigger('tbwchange');
}

How to position ngshow messages in angular js

How to have ng-show messages beside the text box rather than underneath it. Right now it is displaying all the validation messages underneath the input box.
<!DOCTYPE html>
<html ng-app="myApp" >
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script>
"use strict";
var app = angular.module('myApp', []);
app.controller('MainCtrl', function ($scope) {
$scope.cityArray = ["hyderabad", "secunderabad", "delhi", "mumbai"];
$scope.submit = function ($event) {
if ($scope.myForm.$invalid) {
// Or some other update
$scope.myForm.$submitted = true;
$event.preventDefault();
}
};
});
app.directive('uniqueUsername', function ($http) {
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, element, attrs, ngModel) {
element.bind('blur', function (e) {
ngModel.$setValidity('unique', true);
$http.post('CheckUserName2.do').success(function (data) {
if (data) {
ngModel.$setValidity('unique', false);
}
});
});
}
};
});
</script>
</head>
<body ng-controller="MainCtrl">
<div class="container">
<div class="col-md-6 col-md-offset-0">
<div class="panel panel-login">
<div class="panel-body">
<div class="row">
<div class="col-lg-12">
<h2 class="text-muted">Registration form</h2>
<div>
<form name="myForm" action="RegistrationServlet.do" method="POST" >
First name:<input type="text" class="form-control input-sm" name="uname" ng-pattern="/^[a-zA-Z]{3,20}/" ng-model="uname" unique-username="" placeholder="First Name" required/>
<span style="color:red" ng-show="myForm.uname.$error.pattern">First name cannot be less than 3 letters with no digits</span>
<span style="color:red" class="error" ng-if="myForm.$submitted && myForm.uname.$error.required">Please fill field above<br></span><br/>
<span style="color:red" class="hide-while-in-focus" ng-show="myForm.uname.$error.unique">Username already exist<br/></span>
<button class="form-control btn btn-success" type="submit" ng-click="submit($event)">Submit</button>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
Here's the plunker
You don't have space to the right to display error messages beside the input box. Putting error messages just above the submit button will cause a minor UI issue: with each error, your form submit-button will flicker vertically.
Viz.
- Submit your form without entering any input to get the error message.
- type/erase any character in the input box to see the flickering
Workaround:
Either keep the error messages below submit button or provide dedicated height to error messages to avoid undesirable effects or both
<form name="myForm" action="RegistrationServlet.do" method="POST" >
First name:<input type="text" class="form-control input-sm" name="uname" ng-pattern="/^[a-zA-Z]{3,20}/" ng-model="uname" unique-username="" placeholder="First Name" required/><br><br>
<button class="form-control btn btn-success" type="submit" ng-click="submit($event)">Submit</button>
<div style="height=100px">
<span style="color:red" ng-show="myForm.uname.$error.pattern">First name cannot be less than 3 letters with no digits</span>
<span style="color:red" class="error" ng-if="myForm.$submitted && myForm.uname.$error.required">Please fill field above<br></span><br/>
<span style="color:red" class="hide-while-in-focus" ng-show="myForm.uname.$error.unique">Username already exist<br/></span>
</div>
</form>
Demo

Resources