I need to show address every time it changes in Google Maps Autocomplete input.
The problem is that it does work only when I'm typing the text. When it shows options and I choose one of the addresses, it does not write the address.
<div class="col-6">
<div class="form-group form-group-default">
<label for="maps_autocomplete">Adresa</label>
<input type="text" id="maps_autocomplete" class="form-control" v-model="address">
</div>
</div>
address:[[address]]
<script>
var app = new Vue({
delimiters: ['[[', ']]'],
el: '#app',
data: {
address: '',
business_type_text: '',
},
methods: {}
});
</script>
How to make it react on choosing maps option?
EDIT
I tried to use change event:
<input type="text" id="maps_autocomplete" class="form-control" v-bind:value="address" v-on:change="address = $event.target.value">
Which works when I choose option, but it writes only the characters type inside the input, not the whole address.
So if I write:
"Wash"
And I select:
"Washington"
It shows just "address:Wash"
Related
I'm currently trying to change the default invalid text from form inputs using the code below. The way I'm trying to do it works if the text is static but in my case, the text must be dynamic so I have to put in some sort of prop/data value instead. This is because users will have the ability to toggle between English and Chinese text. I've tried using #invalid and :oninvalid but those don't seem to work. Would anyone be able to help me get through this issue?
<input
ref="firstInput1"
type="email"
v-model="email"
oninvalid="this.setCustomValidity('custom text on invalid')"
onchange="this.setCustomValidity('')"
:placeholder="Email"
required
/>
oninvalid and onchange are the two key components to making this work. Hopefully we can find out how to do this with dynamic text.
For change event in Vue input you should use #change (not onchange)
And I think this sample can help you to set vue validation on email
<div class="container" id="app">
<div :class="['input-group', isEmailValid()]">
<span class="input-group-addon" id="basic-addon1"><span class="fa fa-envelope"></span></span>
<input type="email" class="form-control" placeholder="Email Address" v-model="email" />
</div>
</div>
and
new Vue({
el: '#app',
data: {
email: '',
reg: /^(([^<>()\[\]\\.,;:\s#"]+(\.[^<>()\[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,24}))$/
},
methods: {
isEmailValid: function() {
return (this.email == "")? "" : (this.reg.test(this.email)) ? 'has-success' : 'has-error';
}
}
});
I have numeric input field and I'd like to return some results while user is filling the input field.
code
<input type="number" name="bid" v-model="bid.bid" class="form-control">
Logic
Users starts to type numbers in field above
Will get that number -%10 below it
Returned number will change consistently when user changes the input
example:
PS: The reason that I didn't share any watch, mounted, etc. code is
because i don't have any code for this question.
any idea?
You can insert the value directly into the page pretty easily using interpolation:
<div>You get: {{bid.bid * 0.9}}</div>
This is a very simple snippet. Hope it would be useful.
var app = new Vue({
el: '#app',
data: {
bid: 0
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
your bid: <input type="number" name="bid" v-model.number="bid" class="form-control">
<br>
your result: <span>{{bid*0.9}}</span>
</div>
You can use a computed property for that :
new Vue({
el: "#app",
data: {
bid: 1000
},
computed: {
reducedBid() {
return this.bid * 0.9
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<input type="number" name="bid" v-model="bid" class="form-control">
<p>You get {{ reducedBid }}</p>
</div>
Here is a resource on computed properties.
Hope it helps!
How can i let Vue know that the datepicker changed the date?
new Vue({
el: '#app',
data: {
termin: ''
},
computed: {
},
methods: {
}
})
Just an input field:
<div id="app">
<div class="uk-form-icon"><i class="uk-icon-calendar"></i>
<input name="termin" v-model="termin" value="" placeholder="Choose date" type="text" data-uk-datepicker="{format:'DD.MM.YYYY'}" required="required">
</div>
<p>
Date: {{termin}}
</p>
</div>
If you chage the input field by hand Vue gets it, but not after triggering the picker.
https://jsfiddle.net/Honkoman/dfohvcpk/
The quickest way to do this would be to add a handler for the hide event from the datepicker in your Vue.
mounted(){
$(this.$el).on('hide.uk.datepicker', e => this.termin = this.$refs.date.value)
}
Here is your fiddle updated to do that.
However, traditionally, you should wrap jQuery interaction in a wrapper component.
Vue.component("datepicker",{
props:["value"],
template:`
<input ref="date" name="termin" :value="value" placeholder="Choose date" type="text" data-uk-datepicker="{format:'DD.MM.YYYY'}" required="required">
`,
mounted(){
$(this.$el).on('hide.uk.datepicker', e => this.$emit('input', this.$refs.date.value))
}
})
And your template would become
<div class="uk-form-icon"><i class="uk-icon-calendar"></i>
<datepicker v-model="termin"></datepicker>
</div>
And here is your fiddle updated to work with that.
UiKit events + Vue.set :
FIDDLE
$('input[name="termin"]').on('hide.uk.datepicker', function(){
Vue.set(vm, 'termin', document.querySelector('input[name="termin"]').value)
});
Problem Overview
I have a controller with a view model which contains initially an empty array which will be used for storing 'Test Inputs'. I want to provide the user a button to add a new Test Input on the form which adds a new Test Input object to the array and displays the fields needed to edit its properties.
This works when the button is pressed for the first time (but with incorrect binding) but fails to create additional form elements when pressed again.
The Controller with View Model
import {inject} from 'aurelia-framework';
import {HttpClient, json} from 'aurelia-fetch-client';
import {Router} from 'aurelia-router';
import 'fetch';
import toastr from 'toastr';
#inject(HttpClient, Router)
export class create {
constructor(http, router) {
this.vm = {
test: {
id: 0,
description: "",
testOutput: {
id: 0,
valueType: "",
value: ""
},
testInputs: []
}
};
}
}
The user will be able to add a Test Input to the array by pressing a button which delegates to this function:
addTestInput() {
this.vm.test.testInputs.push({
argumentName: "",
valueType: "",
value: ""
});
}
This function pushes to the Test Inputs array in my view model object a new testInput object.
View
In my view I have added a repeat for binding for each object in the TestInputs array. The loop is intending to create the form elements for editing the properties of each Test Input object in the TestInputs array.
<p if.bind="vm.test.testInputs.length === 0">This test has no inputs. Click the button below to add one.</p>
<template if.bind="vm.test.testInputs.length > 0" repeat.for="testInput of vm.test.testInputs">
<div class="form-group">
<label for="testInputArgumentName${$index}">Argument Name</label>
<input value.bind="testInput.argumentName" type="text" class="form-control" id="testInputArgumentName${$index}" placeholder="Argument Name">
</div>
<div class="form-group">
<div class="form-group">
<label for="testInputValueType${$index}">Expected Value Type</label>
<select class="form-control" value.bind="testInput.valueType">
<option repeat.for="valueType of valueTypeList" value.bind="valueType">${valueType}</option>
</select>
</div>
</div>
<div class="form-group">
<label for="testInputValue${$index}">Expected Value</label>
<template if.bind="testInput.valueType === 'Boolean'">
<select class="form-control" value.bind="testInput.valueType">
<option>true</option>
<option>false</option>
</select>
</template>
<template if.bind="testInput.valueType !== 'Boolean'">
<input value.bind="testInput.value" type="text" class="form-control" id="testInputValue${$index}" placeholder="Expected Value">
</template>
</div>
</template>
<button click.delegate="addTestInput()" type="submit" class="btn btn-success">Add Test Input</button> <button type="submit" class="btn btn-success">Create Test</button>
When I first press the Add Test Input button the form elements are added to the page as expected. However if I press the button again the additional from elements for the new object added to the array are not created.
Also the fields seem to be binding to the local loop variable testInput rather than the specific object in the array.
Attempted Solutions
I have had a go using the suggestions at:
Blog Post on Dynamic Forms in Aurelia
Two Way Binding Array in Aurelia
Aurelia Gitter Chat Log - Help
from jsobell
But they don't seem to have worked for me. Anyone have any ideas?
Your problem is simple. You cannot use if and repeat on the same element. Also in your case are redundant with the p on the first line.
Simple do this:
<template repeat.for="testInput of vm.test.testInputs">
...
</template>
You can find more info here
I am using a Google Places autocomplete package with Meteor and if I have the user select a location in one template, the autocomplete won't work again in a different template.
For instance, if the user picks an autocomplete location for an event they are hosting, and then they try to set their profile location in the profile settings, no autocomplete locations pop up.
In fact, if they even activate the autocomplete dropdown on one page (without even selecting one of the options), it won't work on the other page.
Here's my HTML:
<template name="userUpdate">
<script>
window.onload = function() {
var autocomplete = new google.maps.places.Autocomplete(
(document.getElementById('autocomplete')),{types: ['geocode'] }
);
};
</script>
<form class="main form" autocomplete="off">
<label class="control-label" for="location">Location</label>
<div class="controls">
<div id="locationField">
<input id="autocomplete" name="userLocation" class="form-control" autocomplete="off" placeholder="Where you live." type="text">
</div>
</div>
<p>
<h4 id="setLocation">{{currentUser.profile.location}}</h4>
<input id="updateUser" type="submit" class="btn btn-primary" value="Update Profile" />
</p>
</form>
</template>
Here is the second template:
<template name="postSubmit">
<form class="main form" autocomplete="off">
<div class="form-group">
<label class="control-label" for="title">Event Name</label>
<div class="controls">
<input name="title" id="title" type="text" value="" placeholder="Event name" class="form-control"/>
</div>
</div>
<div class="form-group">
<!--begin google test-->
<script>
window.onload = function() {
var autocomplete = new google.maps.places.Autocomplete(
(document.getElementById('autocompleteEventPost')),{types: ['geocode'] }
);
};
</script>
<label class="control-label" for="location">Event Location</label>
<div class="controls">
<!--<input name="location" id="url" type="text" value="" placeholder="The location of the vent" class="form-control"/>-->
<div id="locationField">
<input id="autocompleteEventPost" name="location" autocomplete="off" placeholder="Event Location" type="text">
</div>
</div>
</div>
<input type="submit" value="Submit" class="btn btn-primary"/>
</form>
</template>
I have the mrt:googlemaps package added, and I have set a googlePlaces.js like so:
GoogleMaps.init({
'sensor': true, //optional
'key': '***my api key***', //optional
'language': 'en', //optional
'libraries': 'places'
});
It is notable to state that although the autocomplete does not function again after a file update (with server restart), it will work again after a page refresh from the client.
Basically, I would like to see a perfect example of how to get this working in multiple templates in meteor.js.
The thing is with Google Maps is once you initialize, it only attaches itself on that current DOM instance. When you switch to another page/template, Gmaps seems to lose touch of those bindings you just created and you will have to reinitialize properly.
And you're using window.onload.. that only runs once..
Take a look at moving the <script> code found inside your templates to the rendered template event(s):
var initAutoComplete = function() {
var autocomplete = new google.maps.places.Autocomplete(
(document.getElementById('autocompleteEventPost')),{types: ['geocode'] }
);
};
Template.userUpdate.rendered = initAutoComplete;
Template.postSubmit.rendered = initAutoComplete;
Make sure you get the timings right though.. GoogleMaps API is async after all and may even mess up with this kind of initialization. One thing you could do to avoid this is to wrap the above code in the GoogleMaps.init callback.
Electric Jesus' answer is the answer that worked, HOWEVER: A variable must be declared for each element that is going to use the Google Places Autocomplete API.
His solution:
var initAutoComplete = function() {
var autocomplete = new google.maps.places.Autocomplete(
(document.getElementById('autocompleteEventPost')),{types: ['geocode'] }
);
};
Template.userUpdate.rendered = initAutoComplete;
Template.postSubmit.rendered = initAutoComplete;
There are two separate input fields, one on each template. So, there must be a variable for each input field you want the Places Autocomplete API to work on. I changed the input element ID's back to "autocomplete". Here's my solution. Note the one-to-one ratio of variables to input fields.
var initAutoComplete = function() {
var autocomplete = new google.maps.places.Autocomplete(
(document.getElementById('autocomplete')),{types: ['geocode'] }
);
};
var initAutoCompletePost = function() {
var autocomplete = new google.maps.places.Autocomplete(
(document.getElementById('autocomplete')),{types: ['geocode'] }
);
};
Template.userUpdate.rendered = initAutoComplete;
Template.postSubmit.rendered = initAutoCompletePost;
For others who use this solution, in my working implementation, I have removed the <script> tags from my HTML (there is no more javascript in my templates).
My guess is you should probably change it to class="autocomplete", id shouldn't have duplicate, so document.getElementById('autocomplete') will always return first element it finds. Never worked with google-maps tho, but I think this can be the reason
None of the other answers worked consistently for me so I'm calling initAutoComplete() when the text input is clicked and it works better for me.
Template.myTemplate.events({
'click #autocomplete': function(e,template) {
initAutoComplete();
}
});
var initAutoComplete = function() {
var autocomplete = new google.maps.places.Autocomplete(
(document.getElementById('autocomplete')),{types: ['geocode'] }
);
};
Edit: Not working so great it turns out though, getting this from time to time:
Uncaught TypeError: Cannot read property 'Autocomplete' of undefined