How do i click on the label to upload the file and show the file name in Vue 2 - vue.js

Here is my code but it has not been added logic.
I'm trying to click on the label to upload the file instead of using the input tag.
Apply.vue
<div class="line">
<h6>Upload CV:</h6>
<div class="up-cv">
<button #click="onFileChange" type="button" id="custom-button">
<img src="../../assets/recruit/taicv.svg" alt="" />Upload
</button>
<input id="real-file" type="file" style="display: none" name="image" />
<div class="name-cv">
<h5 id="custom-text">you have not selected the file</h5>
<img onclick="deleteFile()" src="../../assets/recruit/delete.svg" alt="" />
</div>
</div>
</div>
Looking forward to your help, thanks a lot...

I have created one Demo as you want on stackblitz.
link - https://vue-j4h4a6.stackblitz.io/
also I have attached source code here
<template>
<div id="app">
<div class="line">
<h6>Upload CV:</h6>
<div class="up-cv">
<button
#click="onFileChange"
type="button"
id="custom-button"
>
<!-- <img src="../../assets/recruit/taicv.svg" alt="" /> -->
<span class="material-symbols-outlined"> file_upload </span>
Upload
</button>
<input
id="real-file"
type="file"
style="display: none"
name="image"
#change="fileName"
/>
<div class="name-cv">
<h5 v-if="uploadedFileName">{{ uploadedFileName }}</h5>
<h5 v-else id="custom-text">you have not selected the file</h5>
<!-- <img
onclick="deleteFile()"
src="../../assets/recruit/delete.svg"
alt=""
/> -->
<span
v-if="uploadedFileName"
class="material-symbols-outlined deleteBtn"
#click="deleteFile"
>
delete
</span>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'App',
data() {
return {
uploadedFileName: null,
};
},
methods: {
onFileChange() {
document.getElementById('real-file').click();
},
fileName(e) {
this.uploadedFileName = e.target.value;
},
deleteFile() {
this.uploadedFileName = null;
},
},
};
</script>
<style>
#custom-button {
display: inline-block;
border: 1px solid grey;
padding: 10px;
cursor: pointer;
}
#custom-button span {
display: inline-block;
vertical-align: bottom;
}
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
.deleteBtn {
cursor: pointer;
color: red;
}
</style>

Related

couldn't passing the data from axios to data return variable in vuejs

I have an issue in my vue template down below. I fetched data from axios but it couldn't store the data on this.sub_brand variable. console.log(this.sub_brand) is only working for inside axios. here is the full code -
<template>
<div>
<div class="row" >
<div class="col-md-4 pt-5 pl-5">
<div class="product">
<div class="product__images">
<img
src="http://127.0.0.1:8000/images/gsm.jpg"
alt="google pixel 6"
class="product__main-image"
id="main-image"
/>
<div class="product__slider-wrap">
<div class="product__slider">
<img
src="http://127.0.0.1:8000/images/gsm.jpg"
alt="google pixel 6"
class="product__image product__image--active"
/>
<img
src="http://127.0.0.1:8000/images/gsm.jpg"
alt="google pixel 6"
class="product__image"
/>
<img
src="http://127.0.0.1:8000/images/gsm.jpg"
alt="google pixel 6"
class="product__image"
/>
<img
src="http://127.0.0.1:8000/images/gsm.jpg"
alt="google pixel 6"
class="product__image"
/>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-5 pt-5 pr-5">
<h4>{{sub_brand}}</h4>
<!-- <input type="text" class="form-control" name="" id="" v-model="sub_brand"> -->
<h5>Star</h5>
<div class="bg-light mt-4" style="padding: 10px 0px">
<h2 class="pl-4 pt-3">RM869.00</h2>
</div>
<div class="mt-4">
<h3>Variation</h3>
</div>
<div class="bg-light mt-4" style="padding: 10px 0px">
<h5 class="pl-4">Quantity: </h5>
<input type="number" class="form-control pl-4" placeholder="0" style="width: 12%; margin-left: 4%" min="0">
</div>
<div class="row mt-5">
<button class="btn btn-secondary ml-3">Add to Cart</button>
<button class="btn btn-primary ml-3">Buy Now</button>
</div>
<hr class="mt-5">
</div>
<div class="col-md-3 bg-light">
<div class="pl-5">
<h3><strong>Samsung</strong></h3>
</div>
<div class="pl-5 custom_pan">
Chat
Video Chat
View
</div>
<hr>
<div class="pl-5 mt-4 pr-4">
<strong>Shipping Details</strong>
<p style="color: #D1D3D4">2A, Changkat Duta Kiara, Mont Kiara, 50480 Kuala Lumpur, Willayah Persekutuan Kuala Lumpur</p>
<strong>From: China Logistic, Shankal</strong>
<br><br>
<strong>To: Kuala Lumpur, Willayah Persekutuan</strong>
<br><br>
<strong>Shipping Fee: RM8.00</strong>
</div>
<hr>
<div class="pl-5 mt-5">
<h5>Authentic</h5>
<br>
<h5>15 Days Return</h5>
<br>
<h5>Free Shipping</h5>
</div>
<br><br>
</div>
</div>
<div class="row bg-light">
<div class="card">
<div class="card-header">
<h4>Product Description</h4>
</div>
<div class="card-body">
Samsung
</div>
</div>
</div>
<div class="row bg-light">
<div class="card">
<div class="card-header">
<h4>Review</h4>
</div>
<div class="card-body">
Samsung
</div>
</div>
</div>
<div class="row bg-light">
<div class="card">
<div class="card-header">
<h4>You may also like other product from same merchant</h4>
</div>
<div class="card-body">
Samsung
</div>
</div>
</div>
<div class="row bg-light">
<br><br>
</div>
</div>
</template>
<script>
import axios from 'axios';
export default {
mounted() {
// console.log('Component mounted.');
this.fetchProduct();
},
data() {
return{
single_product: [],
sub_brand: "",
product_id: 6,
}
},
methods: {
fetchProduct(){
axios.get('https://admin.globalshopping-mall.site/api/single_sub_brand_detail/'+ this.product_id)
.then(res => {
this.single_product = res.data.data[0];
this.sub_brand = res.data.data[0].GUID;
}).catch(err => {console.log(err);});
},
},
}
</script>
<style>
.card{
margin-top: 2%;
margin-left: 4%;
background-color: white;
width: 71%;
/* height: 30%; */
}
.card-header{
background-color: white
}
.product {
width: 100%;
height: 68%;
}
.product__images {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.product__main-image {
max-width: 500px;
max-height: 600px;
object-fit: cover;
cursor: pointer;
border: 1px solid #070707;
}
.product__slider-wrap {
max-width: 500px;
min-height: 100px;
display: flex;
align-items: center;
}
.product__slider {
width: 98%;
display: flex;
flex-wrap: nowrap;
overflow-x: auto;
padding-left: 2%;
}
.product__image {
max-width: 180px;
max-height: 100px;
object-fit: cover;
cursor: pointer;
opacity: 0.5;
margin: 0.25rem;
border: 1px solid #070707;
}
.product__image:first-child {
margin-left: 0;
}
.product__image:last-child {
margin-right: 0;
}
.product__image:hover {
opacity: 1;
}
.product__image--active {
opacity: 1;
}
.product__slider::-webkit-scrollbar {
height: 10px;
}
.product__slider::-webkit-scrollbar-thumb {
background-color: #D1AD33;
border-radius: 50px;
}
</style>
Look, the problem is, your context this. works inside axios with context of axios
If you want to use context this. of vue component, you have to get data from axios outside.
You have to use async/await for you vue method fetchProduct
Something like that
methods: {
async fetchProduct() {
let result = await axios.get("https://admin.globalshopping-mall.site/api/single_sub_brand_detail/" +this.product_id)
.then((res) => {
return res.data.data[0];
})
.catch((err) => {console.log(err);});
this.single_product = result;
this.sub_brand = result.GUID;
},
},
or
You can save your context this to the variable before axios
and use this variable inside the axios function
Something like this
methods: {
fetchProduct() {
let _this = this;
axios.get("https://admin.globalshopping-mall.site/api/single_sub_brand_detail/" + this.product_id)
.then((res) => {
_this.single_product = res.data.data[0];
_this.sub_brand = res.data.data[0].GUID;
})
.catch((err) => {console.log(err);});
console.log(this);
},
},
Root cause : As axios API calls works asynchronously, But other code will execute synchronously. Hence, While trying to logging this.sub_brand it will work synchronously and will invoke before the axios call (response time might vary).
Solution : If you want to access the API response immediately after a call. You have to use async/await which make promises easier to write.
async makes a function return a Promise
await makes a function wait for a Promise
Live Demo :
methods: {
async fetchProduct(){
const res = await axios.get('https://admin.globalshopping-mall.site/api/single_sub_brand_detail/'+ this.product_id)
.then(res => {
return res.data.data[0];
}).catch(err => {console.log(err);});
}
this.single_product = res;
this.sub_brand = res.GUID;
}

Styling selected value in Vue Select

I'm using vue select. In the dropdown, there are the labels (not only text). Is it possible to have also the label for the selected value?
<div class="form-group row">
<label for="project_status_id" class="col-sm-3 col-form-label">Projekt Status</label>
<div class="col-sm-9">
<v-select :options="resources.activeProjectStatus" :reduce="project_status_id => project_status_id.id" v-model="form.project_status_id" label="name" id="project_status_id" placeholder="Projekt Status" :class="$vSelectStyle($v.form.project_status_id)">
<template v-slot:option="option" >
<div v-html="option.status_label" class="mb-1">
</div>
</template>
</v-select>
<template v-if="$v.form.project_status_id.$error">
<p class="text-danger" v-if="!$v.form.project_status_id.required">
Projekt - Status ist erforderlich!
</p>
</template>
</div>
</div>
Assuming you want the HTML of the status_label, also assuming that status_label is a template string or similar, then use the selected-option slot with the slot's content being the same as your option slot without the class attached.
The key part in the example below is, as mentioned, the selected-option slot:
<!-- Using OP's `option` key -->
<template v-slot:selected-option="option">
<div v-html="option.status_label"></div>
</template>
The example below is a fork of Vue-Select's Codepen example with modifications for the answer.
Vue.config.productionTip = false;
Vue.component('v-select', VueSelect.VueSelect);
new Vue({
el: '#app',
data: {
options: [
{
name: `<span style="padding: 4px; background: green; border-radius: 0.25rem; color: white;">Foo</span>`
},
{
name: `<span style="padding: 4px; background: orange; border-radius: 0.25rem; color: white;">Bar</span>`
},
{
name: `<span style="padding: 4px; background: red; border-radius: 0.25rem; color: white;">Baz</span>`
}
]
}
});
body {
font-family: 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif;
}
h1 {
font-size: 26px;
font-weight: 600;
color: #2c3e5099;
text-rendering: optimizelegibility;
-moz-osx-font-smoothing: grayscale;
-moz-text-size-adjust: none;
}
#app {
max-width: 30em;
margin: 1em auto;
}
<script src="https://unpkg.com/vue#latest"></script>
<script src="https://unpkg.com/vue-select#latest"></script>
<link rel="stylesheet" href="https://unpkg.com/vue-select#latest/dist/vue-select.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:600">
<div id="app">
<h1>Vue Select</h1>
<v-select :options="options" label="label">
<template v-slot:option="option" >
<div v-html="option.name" style="padding: 2px 0;"></div>
</template>
<template v-slot:selected-option="option">
<div v-html="option.name"></div>
</template>
</v-select>
</div>

VueJS: How to add a boolean prop to existing template

I am looking to extend a vue-toggle component I found to add a boolean value. I am trying to add ability to hide/show an element based on the boolean prop.
Here is my html code:
<div class="container" id="app">
<div class="row">
<div class="col-xs-3 col-sm-4 col-md-5 col-lg-6">
<img src="https://images-na.ssl-images-amazon.com/images/I/81UxhkSlBjL._UX466_.jpg" alt="" class="img-responsive" />
</div>
<div class="col-xs-9 col-sm-8 col-md-7 col-lg-6 options">
<fieldset class="form-group">
<legend class="sr-only">Style</legend>
<div class="form-group">
<vue-toggle :values="styles" :boolean="showVNeck" :selected.sync="style" default="crew"></vue-toggle>
</div>
</fieldset>
<div><span v-if="showVNeck">V Neck</span><span v-else>Crew Neck</span> Selected</div>
</div>
</div>
</div>
<template id="vue-toggle">
<div class="btn-group">
<button type="button"
v-for="(val, key) in values"
#click="changeSelectVal(key, boolean)"
:class="['btn', { 'btn-primary': selected === key, 'btn-default': selected !== key }]"
>{{ val }}</button>
</div>
</template>
Here is my javascript:
var Toggle = Vue.extend({
template: '#vue-toggle',
props: ['values','selected','boolean','default'],
mounted: function () {
this.selected = this.default;
},
methods: {
changeSelectVal: function(val, boolean) {
this.selected = val;
this.boolean = !this.boolean;
}
}
});
Vue.component('vue-toggle', Toggle);
new Vue({
el: '#app',
data: {
style: '',
showVNeck: false,
styles: {
'crew': 'Crew Neck',
'vneck': 'V-Neck',
}
}
});
Here is a codepen to share:
https://codepen.io/mujaji/pen/YzXVqaL
I think I am just overlooking something and looking for assistance.
Cheers!
The .sync modifier requires that your child emits events of the type update:myPropName instead of directly mutating the prop - look at the documentation:
var Toggle = Vue.extend({
template: '#vue-toggle',
props: ['values','selected','boolean','default'],
mounted: function () {
this.$emit('update:selected',this.default);
},
methods: {
changeSelectVal: function(val, boolean) {
this.$emit('update:selected',val);
this.$emit('update:boolean',!this.boolean);
}
}
});
Vue.component('vue-toggle', Toggle);
new Vue({
el: '#app',
data: {
style: '',
showVNeck: false,
styles: {
'crew': 'Crew Neck',
'vneck': 'V-Neck',
},
},
methods:
{
updateVNeck(newValue)
{
this.showVNeck = newValue;
}
}
});
body {
background-color: #5c4084;
padding: 50px;
}
.container {
background-color: #fff;
padding-top: 40px;
padding-bottom: 80px;
border-radius: 8px;
}
.heading
h1 {
color: #fff;
font-size: 4rem;
font-weight: 900;
margin: 0 0 5px 0;
background: -webkit-linear-gradient(#fff, #999);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-align: center;
}
.heading h4 {
color: #5c3d86;
font-size: 24px;
font-weight: 400;
text-align: center;
margin: 0 0 35px 0;
}
.options {
padding-top: 80px;
}
.btn{
outline: none !important;
}
.btn.btn-primary {
background-color: #5c4084;
border-color: #5c4084;
outline: none;
}
.btn.btn-primary:hover {
background-color: #5c4084;
border-color: #5c4084;
}
.btn.btn-primary:active, .btn.btn-primary:focus {
background-color: #5c4084;
border-color: #5c4084;
}
.btn.btn-default:hover {
background-color: #5c4084;
border-color: #5c4084;
color: #fff;
}
.btn.btn-default:active, .btn.btn-default:focus {
background-color: #5c4084;
border-color: #5c4084;
color: #fff;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.3/css/font-awesome.min.css">
<div class="container" id="app">
<div class="row">
<div class="col-xs-3 col-sm-4 col-md-5 col-lg-6">
<img src="https://images-na.ssl-images-amazon.com/images/I/81UxhkSlBjL._UX466_.jpg" alt="" class="img-responsive" />
</div>
<div class="col-xs-9 col-sm-8 col-md-7 col-lg-6 options">
<fieldset class="form-group">
<legend class="sr-only">Style</legend>
<div class="form-group">
<vue-toggle :values="styles" :boolean.sync="showVNeck" :selected.sync="style" default="crew"></vue-toggle>
</div>
</fieldset>
<div><span v-if="showVNeck">V Neck</span><span v-else>Crew Neck</span> Selected</div>
</div>
</div>
</div>
<template id="vue-toggle">
<div class="btn-group">
<button type="button"
v-for="(val, key) in values"
#click="changeSelectVal(key, boolean)"
:class="['btn', { 'btn-primary': selected === key, 'btn-default': selected !== key }]"
>{{ val }}</button>
</div>
</template>

amp-img not showing in carousel

I used an AMP carousel to show a list of articles abstracts.
For some reason only the abstracts which were visible at page load have pictures.
( If i rotate the screen more but not all pictures are loaded. )
What am i doing wrong?
Feel free to ask for more info.
Here's the layout:
<amp-carousel class="articles-carousel" layout="fixed-height" height="200" type="carousel">
<article role="button" tabindex="1" class="article-abstract" on="tap:AMP.setState({selectedArticle:1072}),AMP.scrollTo('id' = 'article_1072')">
<footer>
<amp-img height="128" layout="fixed" src="/server/929/rabbis/11.jpg" width="128"/>
<div class="article-abstract-author">
<address>
<a rel="author">הרב דוד חי הכהן</a>
</address>
</div>
</footer>
<header>
<a class="article-external-link-container" href="/929/307/1072" target="_blank">
<i class="fas fa-external-link-alt"/>
</a>
<h1>נקודות אור בימי אחאב(2)</h1>
</header>
</article>
<article role="button" tabindex="2" class="article-abstract" on="tap:AMP.setState({selectedArticle:1108}),AMP.scrollTo('id' = 'article_1108')">
<footer>
<amp-img height="128" layout="fixed" src="/server/929/rabbis/24.jpg" width="128"/>
<div class="article-abstract-author">
<address>
<a rel="author">הרב חיים בן סניור</a>
</address>
</div>
</footer>
<header>
<a class="article-external-link-container" href="/929/307/1108" target="_blank">
<i class="fas fa-external-link-alt"/>
</a>
<h1>מלחמת אחאב ובן הדד</h1>
</header>
</article>
<article role="button" tabindex="3" class="article-abstract" on="tap:AMP.setState({selectedArticle:1112}),AMP.scrollTo('id' = 'article_1112')">
<footer>
<amp-img height="128" layout="fixed" src="/server/929/rabbis/6.jpg" width="128"/>
<div class="article-abstract-author">
<address>
<a rel="author">הרב צבי שוויגר</a>
</address>
</div>
</footer>
<header>
<a class="article-external-link-container" href="/929/307/1112" target="_blank">
<i class="fas fa-external-link-alt"/>
</a>
<h1>המוותר על דברי נביא</h1>
</header>
</article>
<article role="button" tabindex="4" class="article-abstract" on="tap:AMP.setState({selectedArticle:1113}),AMP.scrollTo('id' = 'article_1113')">
<footer>
<amp-img height="128" layout="fixed" src="/server/929/rabbis/6.jpg" width="128"/>
<div class="article-abstract-author">
<address>
<a rel="author">הרב צבי שוויגר</a>
</address>
</div>
</footer>
<header>
<a class="article-external-link-container" href="/929/307/1113" target="_blank">
<i class="fas fa-external-link-alt"/>
</a>
<h1>עונש אחאב</h1>
</header>
</article>
</amp-carousel>
Here's the stylesheet:
.articles-carousel {
padding: 1em 0;
}
.article-abstract {
text-align: center;
vertical-align: text-top;
width: 155px;
height: 200px;
}
.article-abstract:focus {
outline: none;
}
.article-abstract:first-child {
margin-right: 12px;
}
.article-abstract header {
display: table;
width: 141px;
max-width: 100%;
}
.article-abstract h1 {
display: table-cell;
font-size: 12px;
line-break: normal;
margin: 0;
text-align: center;
width: 128px;
word-break: break-word;
white-space: normal;
}
.article-abstract footer {
display: inline-flex;
}
.article-abstract-author {
margin: 0px 3px 0 0;
max-width: 12px;
}
.article-abstract-author address {
transform: rotate(-90deg);
}
.article-abstract-author a {
font-size: 11px;
}
.article-external-link-container {
display: block;
width: 16px;
}
You can see that only three of four pictures appeared:
UPDATE:
Bachcha Singh says it's a bug. After adding:
.articles-carousel {
direction:ltr;
}
.articles-carousel > div * {
direction:rtl;
}
it now works. However, i will be glad to make it at least feel like rtl... say with setting initial position to carousel end.
UPDATE#2:
Seems to be solved in amp-carousel-0.2.
Nothing is wrong with your code, after some R & D I found that This is a bug in rtl handling of lazy loading.
For now you can change the direction for amp-carousel and set the design according to your need, Till AMP team will not fixed this bug.
.articles-carousel { direction:ltr; }
If you can change the amp-carousel type carousel to slides, than its also work.

search button to open search box in bootstrap navbar

I want to add search box to my navbar but not as the traditional way as appears in the picture , I want to add a search icon button in the navbar only and when user click on it the search box appears under the search icon .
How can i do this any one can help me please ?
<nav class="navbar navbar-default" role="navigation">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Brand</a>
</div>
<div class="collapse navbar-collapse" >
<ul class="nav navbar-nav">
<li class="active">Home</li>
<li>Contact US</li>
<li class="dropdown">
Who we are <b class="caret"></b>
<ul class="dropdown-menu">
<li>About</li>
<li> Mession</li>
<li> Vision</li>
<li class="divider"></li>
<li>Goals</li>
</ul>
</li>
<li>Publications</li>
<li>Media</li>
<li>Partners</li>
</ul>
There are lot of things on the net e.g https://www.w3schools.com/howto/tryit.asp?filename=tryhow_css_anim_search
Run below code:
<!DOCTYPE html>
<html>
<head>
<style>
input[type=text] {
width: 130px;
box-sizing: border-box;
border: 2px solid #ccc;
border-radius: 4px;
font-size: 16px;
background-color: white;
background-image: url('https://www.w3schools.com/howto/searchicon.png');
background-position: 10px 10px;
background-repeat: no-repeat;
padding: 12px 20px 12px 40px;
-webkit-transition: width 0.4s ease-in-out;
transition: width 0.4s ease-in-out;
}
input[type=text]:focus {
width: 100%;
}
</style>
</head>
<body>
<p>Animated search form:</p>
<form>
<input type="text" name="search" placeholder="Search..">
</form>
</body>
</html>
You can try these snippets.
Solutuion with CSS Only:
.hide
{
opacity: 0;
max-height: 0;
}
#trigger {
position: absolute;
left: -999em;
}
#container input[type="checkbox"]:checked + div
{
max-height: 99em;
opacity: 1;
height: auto;
overflow: hidden;
}
<div id="container">
<label for="trigger">click me for Search</label>
<input type="checkbox" id="trigger">
<div class="hide">
<form>
<input type="text" name="search" placeholder="Search..">
</form>
</div>
<div>
Solution with JS:
function myFunction() {
if (document.getElementById("form").style.display === "none") {
document.getElementById("form").style.display = "block";
} else {
document.getElementById("form").style.display = "none";
}
}
button {
width: 50px;
height: 50px;
}
<p>show and hide search</p>
<button onclick="myFunction()"></button>
<form id="form">
<input type="text" name="search" placeholder="Search..">
</form>