I need to clean up the google autocomplete input after select a location. I assigned a data value to the value prop of the component but seems like it doesn't change. Even using a watch, seem's like nothing happens.
This is my InputPlace component:
<template>
<label class="form-label-place" for="city">
<input class="form-control pr-5" :value="value" type="text" id="inputPlace" name="city" placeholder="Ingresa tu ciudad">
</label>
</template>
<script>
export default {
name: 'input-place',
props: {
value: ''
},
mounted() {
// Google autocomplete
const options = {
types: ['(cities)'],
componentRestrictions: {country: "PE"}
};
const places = new google.maps.places.Autocomplete(document.getElementById('inputPlace'), options);
google.maps.event.addListener(places, 'place_changed', () => {
this.$parent.placeChanged(places)
});
}
}
</script>
And this is how i'm using it into the view:
<template>
...
<input-place :value="InputPlaceValue"></input-place>
</template>
<script>
...
data() {
return {
activePlaces: [],
InputPlaceValue: ''
}
},
methods: {
placeChanged(places) {
let placeName = places.getPlace().name;
if(!this.activePlaces.includes(placeName)) this.activePlaces.push(placeName)
this.InputPlaceValue = ''
}
}
</script>
Hope you can help me, Thank you.
One option to clear autocomplete text field would be to:
a) use v-model directive
<input v-model="selectedAddress" class="form-control pr-5" type="text" id="inputPlace" name="city" placeholder="Ingresa tu ciudad">
b) and clear input value once place_changed event is triggered like this:
google.maps.event.addListener(places, "place_changed", () => {
this.selectedAddress = "";
});
InputPlace.vue example
<template>
<label class="form-label-place" for="city">
<input class="form-control" type="text" id="inputPlace" v-model="selectedAddress" name="city" placeholder="Search..">
</label>
</template>
<script>
export default {
/* global google */
name: "input-place",
data () {
return {
selectedAddress: ''
}
},
mounted() {
const options = {
types: ["(cities)"]
};
const places = new google.maps.places.Autocomplete(
document.getElementById("inputPlace"),
options
);
google.maps.event.addListener(places, "place_changed", () => {
this.selectedAddress = "";
this.$parent.placeChanged(places)
});
}
};
</script>
Related
I got the problem when implementing form input validation in React.
Once I open the form, there is always [object object] appear as the default input.
Here is the display:
Ideally, I want to have the below display:
And here is my code, any idea how shall I fix it?
const ErrorValidationLabel = ({ txtLbl }) => (
<label htmlFor="" style={{ color: "red" }}>
{txtLbl}
</label>
);
const txtFieldState = {
value: "",
valid:true,
}
class Setting extends Component {
constructor() {
this.state = {
name: {...txtFieldState, fileName:"name", required:true, requiredTxt:"Device ID is required"} ,
}
this.handleNameChange = this.handleNameChange.bind(this);
this.handleNameSearch = this.handleNameSearch.bind(this);
handleNameChange(event) {
this.setState({ name: event.target.value });
}
handleNameSearch(event) {
//http request call logic
}
}
render() {
const renderNameError = this.state.name.valid? "" : <ErrorValidationLabel txtLbl={this.state.name.requiredTxt} />;
return (
<form onSubmit={this.handleNameSearch}>
<label >
Enter Your Device Id:
</label>
<Input name="name" type="text" placeholder="ex:12345678910" value={this.state.name} onChange={this.handleNameChange} required/>
{renderNameError}
<Input type="submit" value="Search Device" />
</form>
);
}
You're setting the value of your input to this.state.name, but this.state.name is an object.
this.state = {
name: {...txtFieldState, fileName:"name", required:true, requiredTxt:"Device ID is required"}
}
You should set it to this.state.name.value.
I should warn you, however, that the code this.setState({ name: event.target.value }) will overwrite your entire name object, which likely isn't what you want.
You're using a spread operator already, so I would suggest
this.setState(state => ({ name: { ...state.name, value: event.target.value } }))`.
Here is a basic setup for what I would like to do:
HTML Side
test.html
<div id="app">
<my-comp temp="1" cat="{ name:'Geoff', age:3 }"></my-comp>
</div>
Vue Side
app.js:
import myComp from './components/myComp.vue'
app = new Vue({
el: "#app",
components: {
myComp
}
});
myComp.vue
<template>
<div v-html='template'>
</div>
</template>
<script>
export default {
props: [
'temp',
'cat'
],
data () {
temp1: `<input name="name" value="cat.name">
<input name="age" value="cat.age">`,
// other template
// ...
},
computed: {
template() {
return this.temp == 1 ? this.temp1 : this.temp2;
}
}
}
</script>
My problem is when I open the html file in the browser, I get:
cat.name
cat.age
appearing in the input. Technically, my form isn't responsive to existing data. How can I solve this?
In your test.html you have to change this:
<my-comp :temp="1" :cat="{ name:'Geoff', age:3 }"></my-comp>
The double dots have to added otherwise it will be interpreted as an string and not as an object.
With value you are on the right track. The only you have to change is this because you want to insert a variable into your 'string'
data() {
return {
temp1: `<input name="name" value="${this.cat.name}">
<input name="age" value="${this.cat.age}">`
}
}
Don't forget to add 'input type' as well.
I am writing a login page with register and login options using AngularJS. There are three input fields: username, password and name. I want name field to appear when I click to register button and disappear when I click to login button. Therefore I want to change input field's class to 'hidden' on click and let css handle the job. How can I do it using AngularJS? Is there a better way to hide the name input field?
HTML:
<h2>Welcome to Mail Service</h2>
<form action="/action_page.php">
<div class="imgcontainer">
<img src="images/img_avatar2.png" alt="Avatar" class="avatar">
</div>
<div class="container">
<label><b>Username</b></label><br>
<input type="text" placeholder="Enter Username" name="uname" required ng-model="user.username"><br>
<label><b>Password</b></label><br>
<input type="password" placeholder="Enter Password" name="psw" required ng-model="user.password"><br>
<!-- NAME INPUT FIELD -->
<div class="textField-hidden">
<label><b>Name</b></label><br>
<input type="text" placeholder="Enter Name" ng-model="user.name">
</div><br>
<button type="submit" ng-click="login()">Login</button><br>
<button type="submit" ng-click="register()">Register</button>
</div>
</form>
AngularJS Controller:
app.controller('LoginCtrl', ['$scope', '$resource', '$location',
function($scope, $resource, $location)
{
$scope.login = function()
{
var loginRequest = $resource('/api/login');
loginRequest.save($scope.user, function(response)
{
});
};
$scope.register = function()
{
var registerRequest = $resource('/api/register');
loginRequest.save($scope.user, function(response)
{
});
};
}]);
You need to use ng-hide or ng-show directive (based on your context), and provide it with appropriate condition value like this:
$scope.showName = false;
$scope.login = function() {
// Your code
$scope.showName = false;
}
$scope.register = function() {
// Your code
$scope.showName = false;
}
Change your HTML accordingly:
<input ng-show="showName" type="{{type}}" placeholder="Enter Name" ng-model="user.name">
In this way, the input box will be shown only if the expression of ng-show evaluates to true. Alternatively, ng-if can be used similar to ng-show, but it works a bit different.
just populate a variable as true when you click register and set that variable as false when you click login.
<h2>Welcome to Mail Service</h2>
<form action="/action_page.php">
<div class="imgcontainer">
<img src="images/img_avatar2.png" alt="Avatar" class="avatar">
</div>
<div class="container">
<label><b>Username</b></label><br>
<input type="text" placeholder="Enter Username" name="uname" required ng-model="user.username"><br>
<label><b>Password</b></label><br>
<input type="password" placeholder="Enter Password" name="psw" required ng-model="user.password"><br>
<!-- NAME INPUT FIELD -->
<div class="textField-hidden" ng-show="register">
<label><b>Name</b></label><br>
<input type="text" placeholder="Enter Name" ng-model="user.name">
</div><br>
<button type="submit" ng-click="login()">Login</button><br>
<button type="submit" ng-click="register()">Register</button>
now populate $scope.register as true when you click register
app.controller('LoginCtrl', ['$scope', '$resource', '$location',
function($scope, $resource, $location)
{
$scope.register=false;
$scope.login = function()
{
var loginRequest = $resource('/api/login');
$scope.register=false;
loginRequest.save($scope.user, function(response)
{
});
};
$scope.register = function()
{
var registerRequest = $resource('/api/register');
$scope.register=true;
loginRequest.save($scope.user, function(response)
{
});
};
}]);
You can use a variable for input fields type and hide it
HTML:
<input type="{{type}}" placeholder="Enter Name" ng-model="user.name">
JS:
app.controller('LoginCtrl', ['$scope', '$resource', '$location',
function($scope, $resource, $location)
{
$scope.login = function()
{
$scope.type="hidden";
var loginRequest = $resource('/api/login');
loginRequest.save($scope.user, function(response)
{
});
};
$scope.register = function()
{
$scope.type="text";
var registerRequest = $resource('/api/register');
loginRequest.save($scope.user, function(response)
{
});
};
}]);
An alternative will be to use ng-if or ng-hide/ng-show defined on a $scope variable and trigger a boolean value for this variable according to your needs.
This is my HTML form
<form ng-submit='create()'>
..
.
.
<input type='file' ng-model='logo' accept="image/*">
</form>
this is my controller :
$scope.create = function () {
$scope.Ent = {}
$scope.Ent.logo = $scope.logo;
ng-model won't work in input type 'file. use a custom directive to bind it
.directive("fileread", [function () {
return {
scope: {
fileread: "="
},
link: function (scope, element, attributes) {
element.bind("change", function (changeEvent) {
var reader = new FileReader();
reader.onload = function (loadEvent) {
scope.$apply(function () {
scope.fileread = loadEvent.target.result;
});
}
reader.readAsDataURL(changeEvent.target.files[0]);
});
}
}
}]);
assign scope variable to fileread attribute
<form ng-submit='create()'>
..
.
.
<input type='file' fileread='logo' accept="image/*">
</form>
Below is the template I am using for the directive. In code we are
fetching the data from a service in that data we have all the
information of that particular person. And from that data we are
showing only first name, last name and designtion or company
affiliation.
<div ng-if="model" class="entry-added">
<span class="form-control"><b>{{model.fullName}}</b>, <br/><span class="small-font">{{(model.designation)?model.designation:model.companyAffiliation}}</span></span>
<a ng-click="removePerson()" class="action-remove"><i class="fa fa-remove"></i></a>
</div>
<div ng-show="!model" class="input-group">
<input type="text"
class="form-control"
name="{{name}}"
id="{{name}}"
placeholder="{{placeholder}}"
ng-required="{{isRequired}}"
typeahead-on-select = "change($item, $model, $label)"
ng-model="model"
typeahead-min-length="3",
typeahead="suggestion for suggestion in searchEmployees($viewValue)"
typeahead-template-url="typeAheadTemplate.html"
typeahead-loading="searching"
typeahead-editable="false">
<script type="text/ng-template" id="typeAheadTemplate.html">
<a class="ui-corner-all dropdown" tabindex="-1">
<div class="col-md-2"><img class="dropdown-image" ng-src="https://people.***.com/Photos?empno={{match.model.employeeNumber}}"></div>
<div>
<div bind-html-unsafe="match.model.fullName"></div>
<div bind-html-unsafe="match.model.designation"></div>
</div>
</a>
</script>
I am using a custom directive to display a search field. The drop down is displaying [object object].
Directive
// In backend taxDeptContact is a Person type object
/*
Directive code
*/
(function () {
'use strict';
angular.module('treasuryApp.directives').directive('employeeSearch', employeeSearch);
employeeSearch.$inject = ['$resource', '$rootScope', 'ErrorHandler'];
function employeeSearch($resource, $rootScope, ErrorHandler) {
return {
restrict: 'E',
require: '^form',
scope: {
model: "=",
isRequired: '#',
submitted: "=",
onSelect: '&',
name: '#',
index:'#'
},
link: function(scope, el, attrs, formCtrl) {
//set required attribute for dynamically changing validations
scope.searchEmployees = function (searchTerm) {
var users = [];
var myResult = [];
var result = $resource($rootScope.REST_URL + "/user/getEmployees", {term: searchTerm}).query().$promise.then(function (value) {
//console.log(value)
$.each(value, function(i, o) {
users.push(o);
});
return users;
});
return result;
}
scope.removePerson = function() {
scope.model=null;
}
scope.userNotSelectedFromTypeahead = function(name) {
if(undefined === formCtrl[name]) {
return false;
}
return formCtrl[name].$error.editable;
};
scope.change = function(item, model, label) {
scope.model = item
scope.onSelect(
{name: scope.name, person: scope.model});
},
templateUrl: 'app/components/common/directives/employee-search.tpl.html'
};
}
})();
View that is using the directive
<div class="form-group">
<label class="col-sm-3>Tax Dept Contact</label>
<div class="col-sm-4">
<employee-search model="reqCtrl.requestObj.taxDepartmentContact" name="taxDeptContact" is-required="false" submitted="reqCtrl.submitted"/>
</div>
</div>
Image of the error occuring
Looks like this may be your trouble spot
typeahead="suggestion for suggestion in searchEmployees($viewValue)"
suggestion for suggestion is pulling the whole object. Have you tried displaying a particular attribute of suggestion?
For example: if you had a suggestion.name attribute you would write:
typeahead="suggestion.name for suggestion in searchEmployees($viewValue)"
Finally got the answer: I used autocomplete="off" in my directive and thats all
<input type="text" autocomplete="off" />