Use Vue only in part of an existing jQuery project - vue.js

I have an old project and I want to use Vue to make some fields of one of the forms be shown or hidden, I'm importing Vue from CDN and initializing a new Vue app, I've tried setting an id to the body of the project, but it does not work, then I created a div inside the body section wrapping all existing code, but the result is all the content is gone and gives a blank page. If i initialize Vue with the form id now the form is blank.
I've checked that Vue is imported adding a console.log in created lifecycle and it works, the problem is old content of page is missing when I wrap it with id specified in Vue initialization.
Here's my code:
const vueApp = new Vue({
el: '#my-form',
data() {
return {
selectedProductType: "Producto 3x2 o 2x1",
}
},
created() {
console.log("+++++++++++++++++++++++++++++++++++++++++ CREATED");
},
})
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
</head>
<body class="fixed-layout skin-blue-dark p-0" id="page-top" oncopy="return false" oncut="return false" oncontextmenu="return false">
<p>A LOT OF CONTENT HERE</p>
<form action="" method="POST" class="form" id="my-form" data-action="create">
<p>A LOT OF CONTENT HERE</p>
<label for="name">Tipo de producto</label>
<select class="form-control" name="product_type" id="product-type" v-model="selectedProductType" required>
<option value="" disabled selected>Selecciona...</option>
<option value="Producto con descuento">Producto con descuento</option>
<option value="Producto 3x2 o 2x1">Producto 3x2 o 2x1</option>
<option value="Producto en combo">Producto en combo</option>
<option value="Producto no promocional">Producto no promocional</option>
</select>
<br>
{{ selectedProductType }}
</form>
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.16/dist/vue.js"></script>
</body>
</html>
I've tried wrapping parts of code with different div IDs but it never works.
I want to know if it is possible to use Vue in my use case and how to achieve it.
Thanks.
EDIT 1:
I've added some code to current snippet, but I dont't know why it works in the snippet and not in my working code.

It's missing the creation of the Vue component, and the div with the initialisation element id and the vue components tags.
The initialisation part of Vue looks good to me, just make sure to happen after the components are defined.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.16/dist/vue.js"></script>
</head>
<body class="fixed-layout skin-blue-dark p-0" id="page-top" oncopy="return false" oncut="return false" oncontextmenu="return false">
<p>A LOT OF CONTENT HERE</p>
<div id="my-form">
<my-form></my-form>
</div>
<script>
Vue.component('my-form', {
template:`
<form action="" method="POST" class="form" id="my-form" data-action="create">
<p>A LOT OF CONTENT HERE</p>
<label for="name">Tipo de producto</label>
<select class="form-control" name="product_type" id="product-type" v-model="selectedProductType" required>
<option value="" disabled selected>Selecciona...</option>
<option value="Producto con descuento">Producto con descuento</option>
<option value="Producto 3x2 o 2x1">Producto 3x2 o 2x1</option>
<option value="Producto en combo">Producto en combo</option>
<option value="Producto no promocional">Producto no promocional</option>
</select>
<br>
{{ selectedProductType }}
</form>`,
data() {
return {
selectedProductType: "Producto 3x2 o 2x1",
}
}
})
const vueApp = new Vue({
el: '#my-form',
created(){
console.log("+++++++++++++++++++++++++++++++++++++++++ CREATED");
}
})
</script>
</body>
</html>
this should work!

data(){return{}} is needed when you are creating Vue.component, in case of new Vue you need data:{}
Try data:{} instead of data(){return{}} like this:
const vueApp = new Vue({
el: '#my-form',
data: {
selectedProductType: "Producto 3x2 o 2x1"
}
})

It looks like I just needed to set Vue in head section instead of the end of body tag, I added Vue from CDN:
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.16/dist/vue.js"></script>
And then, I initilized it after all components were loaded in the bottom of body tag.

Related

How to bind selectedIndex of a select element with vue?

why can't I bind the selectedIndex property of a select element to a variable with vue and how can I achieve to do it anyway?
I'm trying to synchronize two select elements in a page by the index of the selected option. In order for the synchronization to work, the index must be propagated in both ways: from any element to a vue data variable and from this vue data variable to both elements.
At first, I tried to use v-bind.sync, but since it didn't work, I decided to try the explicit way via v-bind and a v-on:change event handler method. While updating the data variable in the event handler works, the binding doesn't. This is my example code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
</head>
<body>
<div id="app">
<select v-bind:selectedIndex="index" v-on:change="indexChanged">
<option>zero</option>
<option>one</option>
</select>
<select v-bind:selectedIndex="index" v-on:change="indexChanged">
<option>zero</option>
<option>one</option>
</select>
Index stored in vue-app: {{ index }}
</div>
<script>
let app = new Vue({
el: "#app",
data: {
index: 0,
},
methods: {
indexChanged: function(event) {
this.index = event.target.selectedIndex;
}
}
});
</script>
</body>
</html>
One clue I noticed, is that PyCharm complains where I try to bind selectedIndex. The tooltip says: "Unrecognized attribute or property name". (It also says "vue#3.2.0", although version 2.5.17 is in use here, which puzzles me.)
Anyway, I can perfectly get and set the value via the JS console in the browser and the select actually updates its selected option according to the new index.
>> document.getElementsByTagName("select")[0].selectedIndex
<- 0
>> document.getElementsByTagName("select")[0].selectedIndex = 1
<- 1
I looked for another property that holds the selected index' information and the only one I found was .option.selectedIndex. I don't know how to bind this either.
The only way I'm seeing now, is to bypass vue's reactiveness and take the sledgehammer approach:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
</head>
<body>
<div id="app">
<select v-on:change="indexChanged">
<option>zero</option>
<option>one</option>
</select>
<select v-on:change="indexChanged">
<option>zero</option>
<option>one</option>
</select>
Index stored in vue-app: {{ index }}
</div>
<script>
let app = new Vue({
el: "#app",
data: {
index: 0,
},
methods: {
indexChanged: function(event) {
this.index = event.target.selectedIndex;
const selects = document.getElementsByTagName("select");
for (let i = 0; i < selects.length; i++) {
selects[i].selectedIndex = this.index;
}
}
}
});
</script>
</body>
</html>
I'm aware that I could make the connection over the selects' value properties, which store the selected options' text with v-model, but this wouldn't be unambiguous if multiple options had the same text, which (shouldn't, yeah, but) might happen in my case. Is it in fact not possible to bind selectedIndex, because one shouldn't do it since the options' texts should always be unique? I'd be grateful for advice here.
You can also set a unique value for option equal to the array index. Example below:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
</head>
<body>
<div id="app">
<select v-model="selectIndex">
<option v-for="(item, index) in options" :key="index" :value="index">{{ item }}</option>
</select>
<select v-model="selectIndex">
<option v-for="(item, index) in options" :key="index" :value="index">{{ item }}</option>
</select>
Index stored in vue-app: {{ selectIndex }}
</div>
<script>
let app = new Vue({
el: "#app",
data: {
selectIndex: 0,
options: ['zero', 'one']
}
});
</script>
</body>
</html>

Dropdown styling not being applied when added with javascript

So I am trying to dynamically (using javascript) add an input field in a form by clicking the button "Add". The semantic-ui dropdown css styling to the first field since it is not added with javascript. However, after I press add, a new field created by the css styling is not applied.
Here is a link to a demo.
https://jsfiddle.net/traorefly/h83245ju/#&togetherjs=QidJs02nya
Here is my code
<!DOCTYPE html>
<html>
<head>
<title>TOPS</title>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.4.1/semantic.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.4.1/semantic.min.css">
<body>
<div class="ui text container" style="margin-top: 20%">
<form action="" class="ui form">
<div class="field" id="timekeyword">
<label>Segment Start Time/Keywords</label>
<div class="ui action input">
<input type="text" placeholder="Ex: 08:23" name="cut"> <select id="keywords" multiple="multiple" class="ui fluid search dropdown" name="video[keywords][]">
<option value="Absolute">Absolute</option>
<option value="Absolute Two">Absolute Two</option>
</select>
<div class="ui positive button" id="addField">Add</div>
</div>
</div>
</form>
</div>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.4.1/semantic.js"></script>
<script >
$('.dropdown').dropdown();
$('#addField').click(function(){
var html = "<div class=\"field\">" +
" <div class=\"ui action input\">" +
" <input type=\"text\" placeholder=\"Ex: 08:23\" name=\"cut\">" +
"<select id=\"keywords\" multiple=\"multiple\" class=\"ui fluid search dropdown\" name=\"video[keywords][]\"><option value=\"Absolute\">Absolute</option>" +
"<option value=\"Absolute Convergence\">Absolute Convergence</option>" +
"<option value=\"Absolute Maximum\">Absolute Maximum</option>" +
" </div>" +
" </div>"
$('#timekeyword').after(html)
})
</script>
</body>
</html>
fiddle: https://jsfiddle.net/8pcfz2a7/
you should call $('.dropdown').dropdown(); for new elements as well.
so add $('.dropdown').dropdown(); to end of your click handler.
you can also put this in a function called update_ui, for reuse code.

How to get photo place from getPlaceDetails? in VUE

So I have a search box, and after I click "enter", I want to display the photo of the place I've just chose.
I don't really know how to do that, and after some searches on the internet, I've found out of getPlaceDetails API.
This is my index.html
<!DOCTYPE html>
<html lang="en">
<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>test-jest</title>
<script type="text/JavaScript" src="https://maps.googleapis.com/maps/api/js?key=MY_KEY&libraries=places"></script>
</head>
<body>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
My App.vue:
<template>
<div id="app">
<div id="nav">
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link> |
<router-link to="/search">Search</router-link>
</div>
<router-view/>
</div>
</template>
And finally, the superstar, my Search component:
<template>
<div id="search-wrapper">
<div>
<input id="search-input" ref="vue_google_autocomplete"
placeholder="Search"
class="search-location"
onfocus="value = ''"
type="text" />
</div>
</div>
</template>
<script>
export default {
mounted() {
this.autocomplete = new google.maps.places.Autocomplete(
(this.$refs.vue_google_autocomplete),
{types: ['geocode'],componentRestrictions: {country: "us"}}
);
this.autocomplete.addListener('place_changed', () => {
let place = this.autocomplete.getPlace();
let ac = place.address_components;
let lat = place.geometry.location.lat();
let lon = place.geometry.location.lng();
var city = ac[0]["short_name"];
var country = ac[3]["long_name"];
console.log(`You're going to ${city}, which is in ${country}`);
console.log(ac);
});
}
}
</script>
Can someone please help me to to display the photo of the place I'm looking for?
Places are defined within this API as establishments, geographic locations, or prominent points of interest. Most roads etc. do not return images.
Source: https://developers.google.com/places/web-service/intro
Check if your response has an photos[] array, the photo's should be there if it matches the above defined places.

When a new component is inserted all the rest disappears inside the app

I always build my SPA apps with the vue-cli.
This time I'm building a small project and I'm incluing Vue with a script tag.
But I don't understand the following behavior.
// app.js
Vue.component('todo-item', {
template: `<div>Todo Component!</div>`
})
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue App!'
}
})
The HTML index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Title</title>
</head>
<body>
<div id="app">
{{ message }}
<div>
Just some content...
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="./js/app.js"></script>
</body>
</html>
The result is this:
Now, I'll try to add '<todo-item />' Component inside the HTML:
<div id="app">
{{ message }}
<todo-item />
<div>
Just some content...
</div>
</div>
The text 'Just some content...' disappeared:
What Am I doing wrong?
TL;DR;
instead of <todo-item/> use <todo-item></todo-item>
Un-compiled vue.js does not support self-closing html tags.
see style guide:
Unfortunately, HTML doesn’t allow custom elements to be self-closing -
only official “void” elements. That’s why the strategy is only
possible when Vue’s template compiler can reach the template before
the DOM, then serve the DOM spec-compliant HTML.
https://v2.vuejs.org/v2/style-guide/#Self-closing-components-strongly-recommended
and issues in github:
https://github.com/vuejs/vue/issues/1036
https://github.com/vuejs/vue/issues/8664

Possibility of Taking Input from Keyboard or Dropdown menu

This is the chunk of my code
<div class="form-control">
<div class="input-group">
<span class="input-group-addon">
<input type="text" id = "fromuser"></input>
<select id="combobox">
<option value="">Select one...</option>
<option value="abc">abc</option>
<option value="cde">cde</option>
<option value="xyz">xyz</option>
</select>
</span>
<button type="submit">Submit</button>
</div>
</div>
What I am trying to achieve is that the User can either Type the value or select from the dropdown list. The challenge here is that the Input from Keyboard will be different from that given in dropdown. For example, the dropdown has three character string options but the user can type a number such as 10, 20, 30 etc.
Is this type of input allowed possible? If so, can someone help me.
The Closest I could come to my problem is by dropping the select and use autocomplete . The full test code is as follows:-
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>jQuery UI Autocomplete - Default functionality</title>
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script>
$( function() {
var availableTags = [
"abc",
"def",
"xyz"
];
$( "#tags" ).autocomplete({
source: availableTags
});
} );
function myFunction(){
var NameValue = document.forms["FormName"]["tags"].value;
window.alert(NameValue);
}
</script>
</head>
<body>
<form name="FormName" method="post" />
<div class="ui-widget" >
<input name= "tags" id="tags" type="text" onchange="myFunction()"/>
<button name="btn-signup" type="submit" value="Submit">Submit</button>
</div>
</form>
</body>
</html>
I know this is the final solution but maybe a way ahead.