Laravel Request is null? - javascript

I generate an input throught jquery like this:
marker = new google.maps.Marker({
map: map,
position: results[0].geometry.location,
title: address,
draggable: true,
zoom: 19,
icon: pinImages,
shadow: pinShadows
});
lat = results[0].geometry.location.lat();
lng = results[0].geometry.location.lng();
$("#lng").html("<input type=hidden name=lng value=" + lng + ">");
$("#lat").html("<input type=hidden name=lat value=" + lat + ">");
google.maps.event.addListener(marker, 'dragend', function (marker) {
latLng = marker.latLng;
lat = latLng.lat();
lng = latLng.lng();
$("#lng").html("<input type=hidden name=lng value=" + lng + ">");
$("#lat").html("<input type=hidden name=lat value=" + lat + ">");
});
In html it looks like:
<div id="lat" value="53.486755"><input type="hidden" name="lat" value="53.4867546"></div>
<div id="lng" value="-2.054067"><input type="hidden" name="lng" value="-2.054066599999942"></div>
Which to me looks absolutely fine. Now when form is submitted controller is being called:
public function updateEntity(EntityRequestUpdate $request)
{
dd($request->input('lat'));
However data dump is giving me null. Why would it be happening?
EntityRequestUpdate:
public function rules()
{
return [
'name' => 'required|min:3|max:100',
'type' => 'required|exists:entity_types,type',
'email' => 'required|email|max:100',
'building_name' => 'nullable',
'address' => ['required','max:191', new Address],
'town' => ['required','max:191', new Hyphens],
'postcode' => ['required','max:191', new Postcode],
'telephone' => ['nullable','max:191', new Telephone],
'ical' => 'nullable|active_url|max:191',
'eventbrite' => 'nullable|numeric',
'tags' => 'nullable|max:255',
'url' => 'nullable|max:191',
'video' => 'nullable|max:191',
'bio' => 'nullable|max:500',
'main' => 'nullable|max:2000',
'lat' => 'nullable',
'lng' => 'nullable'
];

Related

How to apply google maps api in laravel livewire

I am using laravel livewire for my website and on that web, I created a multi-step form where I have to fetch google maps API in the first step. as I know I have to use wire: ignore when using third-party JavaScript library in Livewire component. but the problem comes when I switch from form step 2 to step 1, where google map is not rendered
This is my livewire view.
<div wire:ignore>
<div id="address-map-container" class="mt-2" style="width:100%;height:320px; ">
<div style="width: 100%; height: 100%" id="address-map"></div>
</div>
</div>
<!-- End Google Maps -->
<!-- Seach in google maps -->
<input type="text" wire:model.lazy="address_address" id="address-input"
class="mt-4 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm sm:text-sm border-gray-300 rounded-md map-input"
placeholder="Search in Google Maps">
<input type="hidden" wire:model.lazy="address_latitude" id="address-latitude" value="0" />
<input type="hidden" wire:model.lazy="address_longitude" id="address-longitude" value="0" />
<!-- End in Seach google maps -->
This is my javascript code.
<script>
function initialize() {
$('form').on('keyup keypress', function(e) {
var keyCode = e.keyCode || e.which;
if (keyCode === 13) {
e.preventDefault();
return false;
}
});
const locationInputs = document.getElementsByClassName("map-input");
const autocompletes = [];
const geocoder = new google.maps.Geocoder;
for (let i = 0; i < locationInputs.length; i++) {
const input = locationInputs[i];
const fieldKey = input.id.replace("-input", "");
const isEdit = document.getElementById(fieldKey + "-latitude").value != '' && document.getElementById(fieldKey + "-longitude").value != '';
const latitude = parseFloat(document.getElementById(fieldKey + "-latitude").value) || -6.251855;
const longitude = parseFloat(document.getElementById(fieldKey + "-longitude").value) || 106.978942;
const map = new google.maps.Map(document.getElementById(fieldKey + '-map'), {
center: {lat: latitude, lng: longitude},
zoom: 15
});
const marker = new google.maps.Marker({
map: map,
position: {lat: latitude, lng: longitude},
});
marker.setVisible(isEdit);
const autocomplete = new google.maps.places.Autocomplete(input);
autocomplete.key = fieldKey;
autocompletes.push({input: input, map: map, marker: marker, autocomplete: autocomplete});
}
for (let i = 0; i < autocompletes.length; i++) {
const input = autocompletes[i].input;
const autocomplete = autocompletes[i].autocomplete;
const map = autocompletes[i].map;
const marker = autocompletes[i].marker;
google.maps.event.addListener(autocomplete, 'place_changed', function () {
marker.setVisible(false);
const place = autocomplete.getPlace();
geocoder.geocode({'placeId': place.place_id}, function (results, status) {
if (status === google.maps.GeocoderStatus.OK) {
const lat = results[0].geometry.location.lat();
const lng = results[0].geometry.location.lng();
setLocationCoordinates(autocomplete.key, lat, lng);
}
});
if (!place.geometry) {
window.alert("No details available for input: '" + place.name + "'");
input.value = "";
return;
}
if (place.geometry.viewport) {
map.fitBounds(place.geometry.viewport);
} else {
map.setCenter(place.geometry.location);
map.setZoom(17);
}
marker.setPosition(place.geometry.location);
marker.setVisible(true);
});
}
}
function setLocationCoordinates(key, lat, lng) {
const latitudeField = document.getElementById(key + "-" + "latitude");
const longitudeField = document.getElementById(key + "-" + "longitude");
latitudeField.value = lat;
longitudeField.value = lng;
Livewire.emit('lat')
}
And this is my livewire controller
// Form properties
public $currentPage = 1;
public $property_name;
public $address_address;
public $postal_code;
public $property_phone_number;
public $number_of_rooms;
public $pages = [
1 => [
'heading' => 'General Information',
'subheading' => 'Enter',
],
2 => [
'heading' => 'Property Detail',
'subheading' => 'Enter',
],
];
private $validationRules = [
1 => [
'property_name' => ['required', 'min:3'],
'address_address' => ['required', 'min:3'],
'postal_code' => ['required', 'min:3'],
'property_phone_number' => ['required', 'min:3'],
'number_of_rooms' => ['required'],
],
2 => [
'password' => ['required', 'string', 'min:8'],
'confirmPassword' => ['required', 'string', 'same:password', 'min:8'],
],
];
public function updated($propertyName)
{
$this->validateOnly($propertyName, $this->validationRules[$this->currentPage]);
}
public function goToNextPage()
{
$this->currentPage++;
}
public function goToPreviousPage()
{
$this->currentPage--;
}
Can someone help me how to emit the google maps API and listen to it in JavaScript, therefore, google maps will always be rendered? Thanks

ajax does not send textbox value of google map lat & lng to controller in mvc

when i click on google map,i get lat & lng as below:
and i have some submit textbox and fill those.
after that,i send form via ajax using below ajax :
<script>
$("#btnAdd").click(function (e) {
e.preventDefault();
var dataa = new window.FormData($("#jobDetails")[0]);
$.ajax({
url: "/Job/Create",
data: dataa,
type: "Post",
contentType: false,
processData: false,
dataType: "Json",
success: function (result) {
$("#result").html(result.id);
},
error: function () {
alert("خطا!");
}
});
});
</script>
but in ActionResult i get lat & lng 0 as below
this is my view code:
<div class="form-group">
#Html.LabelFor(model => model.Job.PickUpAddress.Lat, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Job.PickUpAddress.Lat, new { htmlAttributes = new { #class = "form-control", id = "pickLat", #value = "" } })
#Html.ValidationMessageFor(model => model.Job.PickUpAddress.Lat, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Job.PickUpAddress.Lng, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Job.PickUpAddress.Lng, new { htmlAttributes = new { #class = "form-control", id = "pickLng", #value = "" } })
#Html.ValidationMessageFor(model => model.Job.PickUpAddress.Lng, "", new { #class = "text-danger" })
</div>
</div>
and this is my model:
public double Lat { get; set; }
public double Lng { get; set; }
i dont know why ajax send lat & lng 0. can anybody help me?
i figure that how solve this.lat and lng are string but in model my property was double. i changed double to string and question solved.

Open infowindow by clicking a button in AngularJS

I have used google map using AngularJs which is working fine. However, on clicking any marker infowindow opens but I need to open it by clicking a radio button outside the map, here is the code sample
HTML
<ng-map default-style="true" center="[24.8615, 67.0099]" zoom="11" scroll-wheel="false" zoom-to-inculude-markers="auto">
<info-window id="rider">
<div ng-non-bindable="">
{{vm.store.name}} <br/>
{{vm.store.title}}<br/>
</div>
</info-window>
<marker ng-repeat="(id, store) in vm.stores" id="{{id}}" icon="../assets/images/rider.png"
position="{{store.position}}"
on-click="vm.showStore(event, id)"></marker>
JavaScript/AngularJs
vm.stores = [
{position: [24.8820869, 67.06881520000002], title: 'Bahadrubad'},
{position: [24.8753973, 67.04096709999999], title: 'Mazar e Quaid'},
{position: [24.8758, 67.0230], title: 'Karachi Zoo'},
{position: [24.8532941, 67.01622309999993], title: 'Saddar Town'}
];
NgMap.getMap().then(function (map) {
vm.map = map;
});
vm.showStore = function (e, storeId) {
vm.store = vm.stores[storeId];
vm.map.showInfoWindow('rider', this);
};
Once the radio button list is initialized:
<label data-ng-repeat="store in vm.stores">
<input type="radio" name="storeList" ng-model="store" ng-value="{{store}}" ng-change='vm.showStoreExt({{$index}})' />
{{store.title}}
</label>
you could specify event handler to display info window as shown below:
vm.showStoreExt = function (index) {
vm.store = vm.stores[index];
var marker = vm.map.markers[index];
vm.map.showInfoWindow('rider', marker);
};
Working example
angular.module('mapApp', ['ngMap'])
.controller('mapController', function (NgMap) {
var vm = this;
vm.stores = [
{ position: [24.8820869, 67.06881520000002], title: 'Bahadrubad' },
{ position: [24.8753973, 67.04096709999999], title: 'Mazar e Quaid' },
{ position: [24.8758, 67.0230], title: 'Karachi Zoo' },
{ position: [24.8532941, 67.01622309999993], title: 'Saddar Town' }
];
NgMap.getMap().then(function (map) {
vm.map = map;
});
vm.showStoreExt = function (index) {
vm.store = vm.stores[index];
var marker = vm.map.markers[index];
vm.map.showInfoWindow('rider', marker);
};
vm.showStore = function (e, storeId) {
vm.store = vm.stores[storeId];
vm.map.showInfoWindow('rider', this);
};
});
<script src="https://code.angularjs.org/1.4.8/angular.js"></script>
<script src="https://maps.googleapis.com/maps/api/js"></script>
<script src="https://rawgit.com/allenhwkim/angularjs-google-maps/master/build/scripts/ng-map.js"></script>
<div ng-app="mapApp" ng-controller="mapController as vm">
<label data-ng-repeat="store in vm.stores">
<input type="radio" name="storeList" ng-model="store" ng-value="{{store}}" ng-change='vm.showStoreExt({{$index}})' />
{{store.title}}
</label>
<ng-map default-style="true" center="[24.8615, 67.0099]" zoom="11" scroll-wheel="false" zoom-to-inculude-markers="auto">
<info-window id="rider">
<div ng-non-bindable="">
{{vm.store.name}} <br/> {{vm.store.title}}
<br/>
</div>
</info-window>
<marker ng-repeat="(id, store) in vm.stores" id="{{id}}" position="{{store.position}}" on-click="vm.showStore(event, id)"></marker>
</ng-map>
</div>

How to Use javascript inside a php while loop for displaying map markers

How do i show multiple database entries in loop ? So that it looks like this:
But with multiple markers.
I'm not able to loop javascript in php to show multiple markers. Is it possible to do so?
dataProvider: {
map: "worldLow",
images: [
<?php include ('query.php');
while($row= mysql_fetch_array($fetch)){
$cty = $row['city'];
$lat = $row['lati'];
$lon = $row['longi'];
}?>
{
zoomLevel: 5,
scale: 0.5,
title: "<?php echo $cty;?>",
latitude: <?php echo $lon;?>,
longitude: <?php echo $lat;?>
}]
}
I advise you to use json_encode function so as to avoid problems with extra quotes and other symbols:
dataProvider: {
map: "worldLow",
<?php include ('query.php');
// store all markers here
$markers = array();
while ($row= mysql_fetch_array($fetch)) {
// add new marker data
$markers[] = array(
'zoomLevel' => 5,
'scale' => 0.5,
'title' => $row['city'],
'latitude' => $row['lati'],
'longitude' => $row['longi'],
);
}?>
images: <?=json_encode($markers)?>
}
For further debugging - use developers console and/or see rendered javascript.

How to pass a javascript array to ASP.NET MVC model?

I want to create a field object in ASP.NET MVC and store it to a database. The field should contain its coordinates which the user can select with the google maps api.
And now, how can I pass the coordinates of the markers, which are stored in a javascript array, to the Model´s List?
This is my Controller for this:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using BL;
using MvcAgrarTest.Models;
namespace MvcAgrarTest.Controllers
{
public class FieldsController : Controller
{
private MvcAgrarContext db = new MvcAgrarContext();
// GET: Fields
public ActionResult Index()
{
var field = db.CreateFieldViewModel.Include(f => f.FieldType);
return View(field.ToList());
}
// GET: Fields/Create
public ActionResult Create()
{
var model = new CreateFieldViewModel();
ViewBag.FieldTypeId = new SelectList(db.FieldType, "FieldTypeId", "Name");
return View(model);
}
// POST: Fields/Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(CreateFieldViewModel model, CreateFieldViewModel field, string[] markers)
{
if (ModelState.IsValid)
{
PostCoordinates(markers);
db.CreateFieldViewModel.Add(field);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.FieldTypeId = new SelectList(db.FieldType, "FieldTypeId", "Name", field.FieldTypeId);
return Json(true);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}
}
Here my Create View with the Google Maps script:
#model MvcAgrarTest.Models.CreateFieldViewModel
#{
ViewBag.Title = "Create";
}
<h2>Feld anlegen</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Name, new { htmlAttributes = new { #placeholder = "Feldname", #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Name, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.FieldTypeId, "Feldtyp", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("FieldTypeId", null, "--Feldart auswählen--", htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.FieldTypeId, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Size, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Size, new { htmlAttributes = new { #placeholder = "In Hektar", #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Size, "", new { #class = "text-danger" })
</div>
</div>
<div id="google">
<script src="https://maps.googleapis.com/maps/api/js?sensor=false" type="text/javascript"></script>
<script src="http://ajax.microsoft.com/ajax/jquery/jquery-1.3.2.min.js" type="text/javascript"></script>
<script src="http://ajax.microsoft.com/ajax/jquery.validate/1.5.5/jquery.validate.min.js" type="text/javascript"></script>
<script type="text/javascript">
var map;
function initialize() {
var myLatLng = new google.maps.LatLng(50.617109, 8.065738);
var myOptions = {
zoom: 5,
center: myLatLng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
// array to store markers that has been drawn
var markers = [];
// event listener draw a marker
google.maps.event.addListener(map, 'click', function (e) {
var marker = new google.maps.Marker();
marker.setPosition(e.latLng);
marker.setMap(map);
marker.setVisible(true);
markers.push(marker);
// draw polygon on marker click
// once user clicks on on of the markers
google.maps.event.addListener(marker, 'click', function (e) {
document.getElementById("label").innerHTML = "";
drawPoints(markers);
label.style.borderStyle = "dotted"
for (i = 0; i < markers.length; ++i) {
document.getElementById("label").innerHTML += markers[i].position;
}
// empty the markers array
markers = [];
});
});
}
function drawPoints(markers) {
var poly = new google.maps.Polygon;
var points = [];
for (var i = 0; i < markers.length; i++) {
points.push(markers[i].getPosition());
}
poly.setMap(map);
poly.setPath(points);
poly.setVisible(true);
}
</script>
<body onload="initialize()">
<div id="map_canvas" style="width: 500px; height: 300px"></div>
</body>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Erstellen" class="btn btn-default" />
</div>
</div>
</div>
}
and finally my ViewModel to create the field:
public class CreateFieldViewModel
{
[Key]
[Display(Name="ID")]
public int FieldId { get; set; }
[Required]
[Display(Name="Fieldname")]
public string Name { get; set; }
[Required]
[Display(Name="Fieldtype")]
public int FieldTypeId { get; set; }
[Required]
[Range(0.01, int.MaxValue, ErrorMessage = "The Size can´t be 0 or less")]
[Display(Name="Fieldsize")]
public float Size { get; set; }
[Display(Name="Coordinates")]
public List<string> Coordinates { get; set; }
public virtual FieldType FieldType { get; set; }
}
/edit: Id did it like this now, but it still doesn´t work
changed part from the google maps API:
var passdata = [];
google.maps.event.addListener(marker, "click", function(e){
for (y=0; y<markers.length; ++y){
passdata[y] = markers[y].position
}
drawpoints(markers);
$.ajax({
url: "#Url.Action("Create","Fields")",
typ: "POST",
datatype: "json",
data: JSON.stringify({coordinates: passdata}),
contentType: "application/json; charset=utf-8",
traditional: true,
success: function (data) {
alert(data);
},
});
And the Controller Function:
// GET: Fields/Create
public ActionResult Create()
{
var model = new CreateFieldViewModel();
ViewBag.FieldTypeId = new SelectList(db.FieldType, "FieldTypeId", "Name");
return View(model);
}
// POST: Fields/Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(CreateFieldViewModel field, string[] coordinates)
{
if (ModelState.IsValid)
{
field.Coordinates = coordinates;
db.CreateFieldViewModel.Add(field);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.FieldTypeId = new SelectList(db.FieldType, "FieldTypeId", "Name", field.FieldTypeId);
return View(field);
}
I understood, (looking by you code) that you want to go with submitting form, and not ajax?
If so, you have two choices (known to me):
Create html hidden input and paste there as value serialized JSON of your markers array - but you will have to deserialize this value later. In this example you need to change Coordinates type in your model to string.
JavaScript
// some sample coordinates, you need to extract them from markers
var coordinates = ["12,21","213,231"];
var dataToSend = JSON.stringify(coordinates);
$("#coordinatesInput").val(dataToSend);
HTML
<input hidden id="coordinatesInput" name="model.Coordinates" value=""/>
Create dynamically, using JavaScript (for example append function) many hidden html inputs with name model.Coordinates[i] and value of single coordinate (use some loop).
JavaScript
var coordinates = ["231,2132","312,231","231,321"];
var container = $("#container");
//container, where you will be adding inputs, in you example it could be form-horizontal class
coordinates.forEach(function(val, i){
container.append('<input hidden name="model.Coordinates['+i+']" value="'+val+'">');
});
Of course using AJAX is much better way, and AlexB answer is way to go, but mechanism of it is a little different. It is good to use only AJAX (not form submitting), because in your example you need to use two Actions, one for AJAX and one for form submitting.
You can pass your Javascript array to your controller using an Ajax call :
$.ajax({
url : "#Url.Action("MethodName", "ControllerName")",
contentType : "application/json; charset=utf-8",
dataType : "json",
type : "POST",
data : JSON.stringify({coordinates: markers})
})
(where markers is your JS array to pass to the controller, I guess)
And your controller will look like
public ActionResult MethodName(Single[] coordinates)
{
// ...
}

Categories

Resources