How to show reactive map at meteor/autoform, and get marker full adress

125 views Asked by At

So i've been struggling for a week to make this happen!!!!

In short, my structure is as follows :

Address = new SimpleSchema({
    location: {
        type: Object
    },
    fullAddress: {
        type: String
    },
    country: {
        type: String
    },
    governorate: {
        type: String
    },
    city: {
        type: String
    },
    street: {
        type: String
    },
    building: {
        type: Number
    }
});

Branch = new SimpleSchema({
    address: {
         type: Address
    },
    ....
});

Companies = new Mongo.Collection('companies');
CompanySchema = new SimpleSchema({
    branch: {
       type: [Branch],
       minCount: 1
    },
    ....
});
Companies.attachSchema(CompanySchema);

As you can see, I have an array of branches, with all branch has an address & location.

I want to be able to show a map for each [Branch]/Address when calling autoform like:

{{> quickForm collection="Companies" type="insert" id="company_form"}}

Then, have some map click listener to place a marker, and then reverse geoDecode location to populate the address fields

I have tried following yogiben:autoform-map, but the package is incomplete (has MyLocation button issues zoom exceptions, and cannot show multiple maps per page) thus, cannot be used in production.

I am disparate...Please help!

1

There are 1 answers

0
Roshdy On BEST ANSWER

So, I created my own solution, and I'll share it to benefit any one having the same issue.

I modified yogiben/meteor-autoform-map and added a pull request adding geoCoding feature along with a lot of other stuff.

The following is my current autoform configurations & handling:-

Schema

Location = new SimpleSchema({
    location: {
        type: Object,
        autoform:{
            type: 'map',
            label: false,
            afFieldInput: {
                mapType: 'terrain',
                defaultLat: 30.0444196,
                defaultLng: 31.23571160000006,
                geolocation: true,
                autolocate: true,
                searchBox: true,
                language: function(){ return getUserLanguage(); },
                direction: function(){ return (getUserLanguage() == 'ar')? 'rtl' : 'ltr'; },
                zoom: 16,
                key: Meteor.settings.public.google_maps_key,
                googleMap: {
                    mapTypeControl: false
                },
                geoCoding: true,
                geoCodingCallBack: 'reverseGeoCode',
                animateMarker: true
            }
        }
    },
    placeId: {
        type: String,
        autoform: {
            type: 'hidden'
        },
        autoValue: function(){
            return '';
        }
    },
    createdAt: {
        type: Date,
        autoValue: function(){
            return new Date();
        },
        autoform: {
            type: 'hidden'
        }
    }
});

Address = new SimpleSchema({
    location: {
        type: Location,
        label: function(){
            return (Session.get('lang') == 'ar')? 'الموقع على الخريطة' : 'Map Location';
        }
    },
    country: {
        type: String,
        label: function(){
            return (Session.get('lang') == 'ar')? 'الدولة' : 'Country';
        },
        autoform: {
            afFieldInput: {
                placeholder: function(){
                    return (Session.get('lang') == 'ar')? 'الدولة' : 'Country';
                }
            },
            type: 'hidden'
        }
    },
    governorate: {
        type: String,
        label: function(){
            return (Session.get('lang') == 'ar')? 'المحافطة' : 'Governorate';
        },
        autoform: {
            afFieldInput: {
                placeholder: function(){
                    return (Session.get('lang') == 'ar')? 'المحافظة' : 'Governorate';
                }
            }
        }
    },
    city: {
        type: String,
        label: function(){
            return (Session.get('lang') == 'ar')? 'المدينة' : 'City';
        },
        autoform: {
            afFieldInput: {
                placeholder: function(){
                    return (Session.get('lang') == 'ar')? 'المدينة' : 'City';
                }
            }
        }
    },
    district: {
        type: String,
        label: function(){
            return (Session.get('lang') == 'ar')? 'الحي' : 'District';
        },
        autoform: {
            afFieldInput: {
                placeholder: function(){
                    return (Session.get('lang') == 'ar')? 'الحي' : 'District';
                }
            }
        }
    },
    street: {
        type: String,
        label: function(){
            return (Session.get('lang') == 'ar')? 'الشارع' : 'Street';
        },
        autoform: {
            afFieldInput: {
                placeholder: function(){
                    return (Session.get('lang') == 'ar')? 'اسم \ رقم الشارع' : 'Street Name / Number';
                }
            }
        }
    },
    building: {
        type: String,
        label: function(){
            return (Session.get('lang') == 'ar')? 'رقم المبنى' : 'Building Number';
        },
        regEx: /[\d+\-]/,
        autoform: {
            afFieldInput: {
                placeholder: function(){
                    return (Session.get('lang') == 'ar')? 'رقم المبنى' : 'Building Number';
                }
            },
        }
    },
    createdAt: {
        type: Date,
        autoValue: function(){
            return new Date();
        },
        autoform: {
            type: 'hidden'
        }
    }
});

Branch = new SimpleSchema({
    name: {
        type: String,
        label: function(){
            return (Session.get('lang') == 'ar')? 'اسم الفرع' : 'Branch Name';
        },
        autoform: {
            afFieldInput: {
                placeholder: function(){
                    return (Session.get('lang') == 'ar')? 'اسم الفرع' : 'Branch Name';
                }
            }
        }
    },
    address: {
        type: Address,
        label: function(){
            return (Session.get('lang') == 'ar')? 'العنوان' : 'Address';
        },
        minCount: 1,
        optional: false
    },
    createdAt: {
        type: Date,
        autoValue: function(){
            return new Date();
        },
        autoform: {
            type: 'hidden'
        }
    }
});

CompaniesSchema = new SimpleSchema({
    name: {
        type: String,
        label: function(){
            return (Session.get('lang') == 'ar')? 'اسم الشركة' : 'Company Name';
        },
        autoform: {
            afFieldInput: {
                placeholder: function(){
                    return (Session.get('lang') == 'ar')? 'اسم الشركة' : 'Company Name';
                }
            }
        }
    },
    branches: {
        type: [Branch],
        label: function(){
            return (Session.get('lang') == 'ar')? 'الفرع' : 'Branch';
        }
    },
    createdAt: {
        type: Date,
        autoValue: function(){
            return new Date();
        },
        autoform: {
            type: 'hidden'
        }
    }
});

client/main.js

Meteor.startup(() => {
    // ================================================================ //
    // Functions that need to be global perior to Packages loading      //
    // ================================================================ //
    // Get Initial/Current user language 
    getUserLanguage = function () {
        return Session.get('lang') || Meteor.settings.public.defaultLang;
    };

    // Reverse Geocode location
    // @param t         => Template Instance    - object
    // @param geocoder  => google.map.geocoder  - object
    // @param location  => google.maps.LatLng   - object
    reverseGeoCode = function(t, geocoder, location){
        var latlng = {lat: location.lat(), lng: location.lng()};
        var geoCodingOpt = {
            'location'  : latlng,
            'language'  : Session.get('lang'),
            'region'    : 'eg'
        };

        geocoder.geocode(geoCodingOpt, function(results, status){
            if(status === 'OK'){
                if(results.length !== 0){
                    var address = results[0];
                    var cmp = address.address_components;
                    var pfx = t.data.name.replace(/.location/g,'');
                    var sel = '[name="' + pfx + '.' + 'xx' + '"]';
                    var selObj = {
                        placeId     : sel.replace('xx', 'location.placeId'),
                        country     : sel.replace('xx', 'country'),
                        governorate : sel.replace('xx', 'governorate'),
                        city        : sel.replace('xx', 'city'),
                        district    : sel.replace('xx', 'district'),
                        street      : sel.replace('xx', 'street'),
                        building    : sel.replace('xx', 'building')
                    };

                    // Address Container DOM element
                    $addressElm = $(t.firstNode.closest('.autoform-array-item'));
                    // Place ID
                    $addressElm.find(selObj.placeId).val(address.place_id);
                    // Country
                    $addressElm.find(selObj.country).val(cmp[5].long_name);
                    // Governorate
                    $addressElm.find(selObj.governorate).val(cmp[4].long_name);
                    // City
                    $addressElm.find(selObj.city).val(cmp[3].long_name);
                    // District
                    $addressElm.find(selObj.district).val(cmp[2].long_name);
                    // Street
                    $addressElm.find(selObj.street).val(cmp[1].long_name);
                    // Building
                    $addressElm.find(selObj.building).val(cmp[0].long_name);

                    // Clear DOM refference for Garbage Collection
                    $addressElm.prevObject = null;
                    $addressElm = null;
                }
            }
        });
    }
});

Hope that helps anyone.

Feel free to inquire any elaborations