google place autocomplete address form fro multiple input box - laravel

I am creating google autocomplete address form for multiple input fields. My code is work for single field. now i am changing function so it works for all location. how to avoid repeation of functions in above code for mulitple inputfield? I want to create this address functionality for multiple input box. https://developers.google.com/maps/documentation/javascript/examples/places-autocomplete-addressform i am refer this plz need help
<div class="col-12 mb-3">
<label for="current-location" class="mb-1">Current Location</label>
<input type="text" name="locality" id="locality" class="form-control loc">
</div>
<div class="col-12 mb-3">
<label for="preferred-location" class="mb-1">Preferred Location </label>
<div class="row" id="location_row">
<div class="col-12 mb-2">
<input type="text" name="preferred_location[]" id="preferred_location_1" class="form-control loc" placeholder="Search & Select Location">
</div>
<div class="col-12 mb-2">
<input type="text" name="preferred_location[]" id="preferred_location_2" class="form-control loc" placeholder="Search & Select Location">
</div>
</div>
</div>
<script>
let autocomplete;
let address1Field;
let address2Field;
let postalField;
let inputField ;
function initAutocomplete() {
address1Field = document.querySelector("#locality");
address2Field = document.querySelector("#preferred_location_1");
autocomplete = new google.maps.places.Autocomplete(address1Field, {
componentRestrictions: { country: ["in"] },
fields: ["address_components", "geometry"],
types: ["address"],
});
autocomplete.addListener("place_changed", fillInAddress);
autocomplete2 = new google.maps.places.Autocomplete(address2Field, {
componentRestrictions: { country: ["in"] },
fields: ["address_components", "geometry"],
types: ["address"],
});
autocomplete2.addListener("place_changed", fillInAddress2);
}
function fillInAddress() {
const place = autocomplete.getPlace();
if(place!=undefined) {
for (const component of place.address_components) {
const componentType = component.types[0];
switch (componentType) {
case "locality":
document.querySelector("#locality").value = component.long_name;
break;
}
}
}
}
function fillInAddress2() {
const place = autocomplete2.getPlace();
if(place!=undefined) {
for (const component of place.address_components) {
const componentType = component.types[0];
switch (componentType) {
case "locality":
document.querySelector("#preferred_location_1").value = component.long_name;
break;
}
}
}
}
</script>

Related

Google Places API Autocomplete, how to add a second address

I need to search two addresses on the same webpage, one for location, one for correspondence. The first Google API Address works fine, I then tried duplicating the function and form modifying it, but it doesn't populate the second address, it always tries to populate the first address, can anyone tell me where I am going wrong please? Thanks for your help.
function initMap() {
const componentForm = [
'street_number',
'route',
'location',
'locality',
'administrative_area_level_2',
'postal_code',
];
const autocompleteInput = document.getElementById('location');
const options = {
types: ['(cities)'],
componentRestrictions: { country: 'gb' }
};
const autocomplete = new google.maps.places.Autocomplete(autocompleteInput);
autocomplete.addListener('place_changed', function () {
const place = autocomplete.getPlace();
if (!place.geometry) {
// User entered the name of a Place that was not suggested and
// pressed the Enter key, or the Place Details request failed.
window.alert('No details available for input: \'' + place.name + '\'');
return;
}
fillInAddress(place);
});
function fillInAddress(place) { // optional parameter
const addressNameFormat = {
'street_number': 'short_name',
'route': 'long_name',
'locality': 'long_name',
'administrative_area_level_2': 'short_name',
'postal_code': 'short_name',
};
const getAddressComp = function (type) {
for (const component of place.address_components) {
if (component.types[0] === type) {
return component[addressNameFormat[type]];
}
}
return '';
};
document.getElementById('location').value = getAddressComp('street_number') + ' '
+ getAddressComp('route');
for (const component of componentForm) {
// Location field is handled separately above as it has different logic.
if (component !== 'location') {
document.getElementById(component).value = getAddressComp(component);
}
}
}
}
function initMapAddress2() {
const componentForm = [
'street_number',
'route',
'location',
'locality',
'administrative_area_level_2',
'postal_code',
];
const autocompleteInput = document.getElementById('location2');
const options = {
types: ['(cities)'],
componentRestrictions: { country: 'gb' }
};
const autocomplete2 = new google.maps.places.Autocomplete(autocompleteInput);
autocomplete2.addListener('place_changed', function () {
const place2 = autocomplete2.getPlace();
if (!place2.geometry) {
// User entered the name of a Place that was not suggested and
// pressed the Enter key, or the Place Details request failed.
window.alert('No details available for input: \'' + place2.name + '\'');
return;
}
fillInAddress(place2);
});
function fillInAddress(place2) { // optional parameter
const addressNameFormat = {
'street_number2': 'short_name',
'route2': 'long_name',
'locality2': 'long_name',
'administrative_area_level_22': 'short_name',
'postal_code2': 'short_name',
};
const getAddressComp = function (type) {
for (const component of place2.address_components) {
if (component.types[0] === type) {
return component[addressNameFormat[type]];
}
}
return '';
};
document.getElementById('location2').value = getAddressComp('street_number2') + ' '
+ getAddressComp('route2');
for (const component of componentForm) {
// Location field is handled separately above as it has different logic.
if (component !== 'location2') {
document.getElementById(component).value = getAddressComp(component);
}
}
}
}
<div class="card-container">
<div class="panel">
<div>
<img class="sb-title-icon" src="https://fonts.gstatic.com/s/i/googlematerialicons/location_pin/v5/24px.svg" alt="">
<span class="sb-title">Correspondence Address</span>
</div>
<input type="text" placeholder="Search Address" id="location" />
<input type="text" placeholder="" id="street_number" />
<input type="text" placeholder="" id="route" />
<input type="text" placeholder="" id="locality" />
<div class="half-input-container">
<input type="text" class="half-input" placeholder="" id="administrative_area_level_2" />
<input type="text" class="half-input" placeholder="" id="postal_code" />
</div>
</div>
</div>
<script src="https://maps.googleapis.com/maps/api/js?key=****************Zv_k&libraries=places&callback=initMap&channel=GMPSB_addressselection_v1_cA" async defer></script>
<div class="card-container">
<div class="panel">
<div>
<img class="sb-title-icon" src="https://fonts.gstatic.com/s/i/googlematerialicons/location_pin/v5/24px.svg" alt="">
<span class="sb-title">Location Address</span>
</div>
<input type="text" placeholder="Search Address" id="location2" />
<input type="text" placeholder="" id="street_number2" />
<input type="text" placeholder="" id="route2" />
<input type="text" placeholder="" id="locality2" />
<div class="half-input-container">
<input type="text" class="half-input" placeholder="" id="administrative_area_level_22" />
<input type="text" class="half-input" placeholder="" id="postal_code2" />
</div>
</div>
</div>
<script src="https://maps.googleapis.com/maps/api/js?key=****************Zv_k&libraries=places&callback=initMapAddress2&channel=GMPSB_addressselection_v1_cA" async defer></script>
For anyone else having the same issue, I found a solution here Multiple Address on same page

Toggle form in nested v-for loop in VueJS

I have a list of nested comments. Under each comment, I'd like to add a "reply" button that, when click, show a reply form.
For now, everytime I click a "reply" button, it shows the form. But the thing is, I'd like to show only one form on the whole page. So basically, when I click on "reply" it should close the other form alreay opened and open a new one under the right comment.
Edit :
So I was able to make some slight progress. Now I'm able to only have one active form opening on each level of depth in the nested loop. Obviously, what I'm trying to do now is to only have one at all.
What I did was emitting an event from the child component and handle everything in the parent component. The thing is, it would work great in a non-nested comment list but not so much in my case...
Here is the new code:
In the parentComponent, I have a handleSelected method as such:
handleSelected (id) {
if(this.selectedItem === id)
this.selectedItem = null;
else
this.selectedItem = id;
},
And my childComponent:
<template>
<div v-if="comment">
<div v-bind:style=" iAmSelected ? 'background: red;' : 'background: none;' ">
<p>{{ comment.author.name }}<br />{{ comment.created_at }}</p>
<p>{{ comment.content }}</p>
<button class="button" #click="toggle(comment.id)">Répondre</button>
<button class="button" #click="remove(comment.id)">Supprimer</button>
<div v-show="iAmSelected">
<form #submit.prevent="submit">
<div class="form-group">
<label for="comment">Votre réponse</label>
<textarea class="form-control" name="comment" id="comment" rows="5" v-model="fields.comment"></textarea>
<div v-if="errors && errors.comment" class="text-danger">{{ errors.comment[0] }}</div>
</div>
<button type="submit" class="btn btn-primary">Envoyer</button>
<div v-if="success" class="alert alert-success mt-3">
Votre réponse a bien été envoyée !
</div>
</form>
</div>
</div>
<div v-if="comment.hasReply">
<div style="margin-left: 30px;">
<comment v-for="comment in comments"
:key="comment.id"
:comment="comment" #remove-comment="remove"
:is-selected="selectedItem" #selected="handleSelected($event)">
</comment>
</div>
</div>
</div>
</template>
<script>
import comment from './CommentItem'
export default {
name: 'comment',
props: {
isSelected: Number,
comment: {
required: true,
type: Object,
}
},
data () {
return {
comments: null,
fields: {},
errors: {},
success: false,
loaded: true,
selectedItem: null,
}
},
computed: {
iAmSelected () {
return this.isSelected === this.comment.id;
}
},
methods: {
remove(id) {
this.$emit('remove-comment', id)
},
toggle(id) {
this.$emit('selected', id);
},
handleSelected(id) {
if(this.selectedItem === id)
this.selectedItem = null;
else
this.selectedItem = id;
},
},
mounted(){
if (this.comment.hasReply) {
axios.get('/comment/replies/' + this.comment.id)
.then(response => {
this.comments = response.data
})
}
}
}
</script>
Thanks in advance for your help!

GraphQL Apollo recieving data object undefined

I am doing a mutation, that takes a username and password, and in response from the server it gets a login response.
<Mutation mutation={SIGN_UP}>
{(signUp, data) => (
<form onSubmit={e => {
e.preventDefault();
signUp({
variables: {
user: {
"email": input_email.value as String,
"password": input_password.value as String
}
}
});
console.log("Signup", signUp)
console.log("Data", data.data);
input_email.value = "";
input_password.value = "";
}}>
<div className="col-sm">
<div className="signin__header">Signup IMPACT R&D</div>
</div>
<div className="col-sm signin__input" >
<div className="signin__input__header" >Email</div>
<input className="signin__input__email" type="text" placeholder="Enter email" required ref={node=> {input_email = node}}></input>
<div className="signin__divide-line"></div>
</div>
<div className="col-sm signin__input">
<div className="signin__input__header" >Password</div>
<input className="signin__input__password" type="password" placeholder="Enter password" ref={node=> {input_password = node}}></input>
<div className="signin__divide-line"></div>
</div>
<div className="col-sm-3">
<button className="signin__input__button" type="submit">Sign Up</button>
</div>
</form>
)}
</Mutation>
This is my GraphQLtag.
export const SIGN_UP : any = gql`
mutation Register($user: UserInput!) {
register(user: $user) {
status,
refreshToken,
token,
error
}
}
`;
in the browser network i can see that I receive the data. But still my data object is null, when i try to print it out... HELP!
Found out that i needed to wait for the response with a then promise after the signup
}).then ((res: any) => {
errorMessage = res.data.register.token;
});

ReactJs - Redux State is not updating in a dropdown in the child component

I am trying to update the items in my dropdown as my state updates with players BUT I am failing. Please help.
In the child component I have dropdown in the Skylight dialog box.
I am using following code which prints the dropdown of the array of players from the state. State is updated from the json.php (remote server).
<select name="bowlerId" value={this.state.bowlerId} onChange={this.handleInputChange} className="form-control">
<option value="">Select an existing bowler</option>
{
this.currState.teamBowling.players.map(function (player, index) {
return <option value="{player}" key={index}>{player}</option>
})
}
</select>
I can clearly see in the console.log that the state is correctly updated and it prints 11 player names. But in the child component it does not update the dropdown.
Surprising enough, in the child component componentWillReceiveProps() does print new player names as they become availble but the dropdown is not updated still.
Please advise.
Console.log output as page loads
BowlingSummary render() Object {id: 0, name: "", runs: 0, overs: 0, balls: 0…}
PropStore Object {id: 0, name: "", runs: 0, overs: 0, balls: 0…}
BowlingAddBowler render() []
Console.log output after few seconds as data is fetched from php
BowlingSummary render() Object {id: 20, name: "Team Bowling", runs: 0, overs: 0, balls: 0…}
componentWillReceiveProps Object {id: 20, name: "Team Bowling", runs: 0, overs: 0, balls: 0…}
BowlingAddBowler render() []
Parent component named BowlingSummary
class BowlingSummary extends Component {
render() {
const { store } = this.context;
const currState = store.getState();
this.isBowlerBowling = false;
console.log('BowlingSummary render()', currState.teamBowling);
return (
<div>
<div className="score-summary-bar">
<div className="row">
<div className="col-xs-4">Bowling</div>
<div className="col-xs-1"></div>
<div className="col-xs-1">Ovr</div>
<div className="col-xs-1">Mdn</div>
<div className="col-xs-1">Run</div>
<div className="col-xs-1">Wkt</div>
<div className="col-xs-1">Econ</div>
<div className="col-xs-1">W</div>
<div className="col-xs-1">N</div>
</div>
</div>
<div className="score-summary-bowling">
<div className="">
{
currState.teamBowling.players.map(function (player, index) {
if ( player.isBowling === true ) {
this.isBowlerBowling = true;
return <BowlingBowler player={player} key={index}/>
}
})
}
</div>
<div className="">
{
this.isBowlerBowling != true &&
<BowlingAddBowler propStore={store} />
}
</div>
</div>
<div className="score-summary-bowling">
<ScoreThisOver />
</div>
</div>
);
}
}
BowlingSummary.contextTypes = {
store: PropTypes.object
}
export default BowlingSummary;
Child component named BowlingAddBowler
class BowlingAddBowler extends Component {
constructor(props, context) {
super(props, context);
// Setup current state
this.currState = this.props.propStore.getState();
console.log('PropStore', this.currState.teamBowling);
// This component state
this.state = {
bowlerId: 0,
bowlerName: '',
markPrevOverFinished: false
};
// Setup variables
this.players = this.props.players;
// Bind this (so that we write short code in the onChange like onChange=this.func)
this.handleInputChange = this.handleInputChange.bind(this);
}
componentWillReceiveProps(nextProps, nextState){
//this.props.something // old value
//nextProps.something // new value
console.log('componentWillReceiveProps', nextProps.propStore.getState().teamBowling);
}
render() {
//console.log('BowlingBowler render()', this.props);
var responsiveWidth = {
width: '90vw',
transform: 'translate(-23%, 0%)'
};
console.log('BowlingAddBowler render()', this.currState.teamBowling.players);
return (
<div className="row">
<div className="col-xs-12">
<button className="btn" onClick={() => this.refs.dialogAddBowler.show()}>No Bowler Selected. Click To Select</button>
</div>
<SkyLight dialogStyles={responsiveWidth} hideOnOverlayClicked ref="dialogAddBowler" title="Select a new bowler">
<div>
<form onSubmit={this.handleSubmit.bind(this)}>
<label className="bg-yellow">
Total <span className="text-red">0</span> for the loss of <span className="text-red">0</span> wickets in <span className="text-red">0</span> overs
</label>
<div className="spacer-horizontal"></div>
<label>Who will bowl the next over ?</label>
<select name="bowlerId" value={this.state.bowlerId} onChange={this.handleInputChange} className="form-control">
<option value="">Select an existing bowler</option>
{
this.currState.teamBowling.players.map(function (player, index) {
return <option value="{player}" key={index}>{player}</option>
})
}
</select>
<div className="spacer-horizontal"></div>
<b>- OR -</b>
<input type="text" name="bowlerName" value={this.state.bowlerName} onChange={this.handleInputChange} className="form-control" />
<div className="spacer-horizontal"></div>
<input type="checkbox" name="markPrevOverFinished" checked={this.state.markPrevOverFinished} onChange={this.handleInputChange}/>
<label> Mark previous over finished</label>
<div className="spacer-horizontal"></div>
<div className="HorizLine"></div>
<div className="text-right">
<button type="submit" className="btn btn-primary"> Save </button>
</div>
</form>
</div>
</SkyLight>
</div>
)
}
}
This code:
this.currState = this.props.propStore.getState();
is in BowlingAddBowler's constructor and only runs first time when the class is instantiated. You can put it in componentWillReceiveProps of BowlingAddBowler too so that it runs when new data comes from server and parent component updates BowlingAddBowler.

Angular2 How to pass a method located in other file

I am quite a noob in Angular2 and typescript.
I want to pass a method from other class in a other file.
This is the file iam talking about in specific i want to pass the method deleteCondition():
export class ConditionBuilderComponent implements OnInit {
conditions: Condition[] = [];
catalog: Condition[] = [];
constructor(private _conditionService: ConditionService) { }
getConditions() {
this._conditionService.getConditions().then(conditions => this.catalog = conditions);
}
ngOnInit() {
this.getConditions();
}
onChange(conditionsIndex, catalogIndex) {
//console.log(selectedCondition);
//console.log(conditionsIndex);
console.log(catalogIndex);
this.conditions[conditionsIndex] = this.catalog[catalogIndex];
}
newCondition() {
this.conditions.push(this.catalog[0]);
}
deleteCondition() {
this.conditions.pop();
}
}
I want to pass the deleteCondition() method to an other file because in the other file this.conditions.pop() is not recognised of course.
First it was like this: https://www.dropbox.com/s/92z2oe7f4w5x2b5/conditions.jpg?dl=0
Here it deletes the last created but i want to delete each condition separately like this:
https://www.dropbox.com/s/ptwq6sk6da4p21k/new.jpg?dl=0
This is the code from the SelectCondition:
import {Component} from 'angular2/core';
import {Condition} from './condition';
import {ConditionBuilderComponent} from "./conditionbuilder.component";
#Component({
selector: 'select-condition',
template: `
<div class="col-xs-3">
<div class="form-group">
<select class="form-control" [(ngModel)]="selectedOperator">
<option *ngFor="#operator of selectOperators">{{operator}}</option>
</select>
</div>
</div>
<div class="col-xs-3">
<div class="form-group">
<div class="input-group">
<span class="btn-file">
<input type="file" (click)="selectFile()" multiple />
</span>
<input type="text" [(ngModel)]="fileValue" class="form-control" readonly>
<span class="input-group-addon">
<span class="glyphicon glyphicon-folder-open"></span>
</span>
</div>
</div>
</div>
<a class="btn btn-danger pull-right" (click)="deleteCondition()"><i class="glyphicon glyphicon-minus"></i></a>
`
})
export class SelectCondition extends Condition {
public name: string = 'select';
public fileValue: string;
public selectedOperator: string = 'in';
public selectOperators: Condition[] = [
"in"
];
selectFile() {
$(document).on('change', '.btn-file :file', function() {
var input = $(this),
numFiles = input.get(0).files ? input.get(0).files.length : 1,
label = input.val().replace(/\\/g, '/').replace(/.*\//, '');
input.trigger('fileselect', [numFiles, label]);
});
$('.btn-file :file').on('fileselect', function(event, numFiles, label) {
var input = $(this).parents('.input-group').find(':text'),
log = numFiles > 1 ? numFiles + ' files selected' : label;
if( input.length ) {
input.val(log);
console.log(input.val());
}
});
}
deleteCondition = () => this.deleteCondition();
}
Please help me out.

Resources