AngularJS directive for Ionic Leaflet - Utilizing Service to switch tileLayer from side menu

I am currently experimenting with developing an ionic app for the leaflet-angularjs-directive. Unfortunately, there are not many demos available for me to test out.

The specific demo I am using is called ionic-leafletjs-map-demo by calendee on GitHub which can be found here.

My issue arises when I try to replicate the LocationsService into another service called HistoricalMapService. Whenever I add the HistoricalMapService, the webpage appears blank when I use "ionic serve". However, when I comment it out, the webpage works fine but without the functionality of the HistoricalMapService.

Below is the code from my mapController.js (js/controller/mapController.js)

angular.module('starter').controller('MapController',
  [ '$scope',
    '$cordovaGeolocation',
    '$stateParams',
    '$ionicModal',
    '$ionicPopup',
    'LocationsService',
    /*'HistoricalMapService',*/
    'InstructionsService',
    function(
      $scope,
      $cordovaGeolocation,
      $stateParams,
      $ionicModal,
      $ionicPopup,
      LocationsService,
      /*HistoricalMapService,*/
      InstructionsService
      ) {

  // Code here...

}]);

If you want to view the code from my historicalMapService (js/services/historicalMapService.js), you can find it here.

Additionally, here is a snippet from my menu.html (templates/menu.html):

<ion-nav-bar class="bar-positive nav-title-slide-ios7">
  <ion-nav-back-button class="button-clear"><i class="icon ion-ios7-arrow-back"></i></ion-nav-back-button>

</ion-nav-bar>

<ion-nav-view name="menuContent" animation="slide-left-right"></ion-nav-view>

In this part of my menu.html, I am working on displaying the Layer's Name and implementing a feature where the user can click on it to switch the map in the TMS TileLayer. Any guidance or suggestions on how to achieve this would be greatly appreciated!

Thank you for your help in advance.

Answer №1

Solved: Updated

Implementing shared attributes in mapController.js

/*angular.module('starter').controller('MapController', ['$scope', 'leafletData',
    function($scope, leafletData) {
            leafletData.getMap().then(function(map) {
                L.GeoIP.centerMapOnPosition(map, 15);
            });
    }
]); */

angular.module('starter').controller('MapController',
  [ '$scope',
    '$cordovaGeolocation',
    '$stateParams',
    '$ionicModal',
    '$ionicPopup',
    '$http',
    'LocationsService',
    'InstructionsService',
    function(
      $scope,
      $cordovaGeolocation,
      $stateParams,
      $ionicModal,
      $ionicPopup,
      $http,
      LocationsService,
      InstructionsService
      ) {

      /**
       * Once state loaded, retrieve the map data and update scope.
       */
      $scope.$on("$stateChangeSuccess", function() {

        $scope.locations = LocationsService.savedLocations;
        $scope.newLocation;

        if(!InstructionsService.instructions.newLocations.seen) {

          var instructionsPopup = $ionicPopup.alert({
            title: 'Add Locations',
            template: InstructionsService.instructions.newLocations.text
          });
          instructionsPopup.then(function(res) {
            InstructionsService.instructions.newLocations.seen = true;
            });

        }

      $scope.basemapLayers = {
        basemap: {
          name: 'BaseMap',
          url: 'https://api.tiles.mapbox.com/v4/sla.c97ab90d/{z}/{x}/{y}.png?access_token=pk.eyJ1Ijoic2xhIiwiYSI6Ik15dE1uclUifQ.ZmSBZxWOZYCSW3m71abSzQ#17',
          type: 'xyz'
        },
        map1955: {
          name: '1955',
          url: 'https://api.tiles.mapbox.com/v4/sla.d62b6062/{z}/{x}/{y}.png?access_token=pk.eyJ1Ijoic2xhIiwiYSI6Ik15dE1uclUifQ.ZmSBZxWOZYCSW3m71abSzQ#17',
          type: 'xyz'
        },
        map1969: {
          name: '1969',
          url: 'https://api.tiles.mapbox.com/v4/sla.d33a760d/{z}/{x}/{y}.png?access_token=pk.eyJ1Ijoic2xhIiwiYSI6Ik15dE1uclUifQ.ZmSBZxWOZYCSW3m71abSzQ#17',
          type: 'xyz'
        },
        map1975: {
          name: '1975',
          url: 'https://api.tiles.mapbox.com/v4/sla.dbfef17c/{z}/{x}/{y}.png?access_token=pk.eyJ1Ijoic2xhIiwiYSI6Ik15dE1uclUifQ.ZmSBZxWOZYCSW3m71abSzQ#17',
          type: 'xyz'
        },
        map1988: {
          name: '1988',
          url: 'https://api.tiles.mapbox.com/v4/sla.65929e4d/{z}/{x}/{y}.png?access_token=pk.eyJ1Ijoic2xhIiwiYSI6Ik15dE1uclUifQ.ZmSBZxWOZYCSW3m71abSzQ#17',
          type: 'xyz'
        },
        map1998: {
          name: '1998',
          url: 'https://api.tiles.mapbox.com/v4/sla.d7a29a60/{z}/{x}/{y}.png?access_token=pk.eyJ1Ijoic2xhIiwiYSI6Ik15dE1uclUifQ.ZmSBZxWOZYCSW3m71abSzQ#17',
          type: 'xyz'
        },
        map2007: {
          name: '2007',
          url: 'https://api.tiles.mapbox.com/v4/sla.7ce67a24/{z}/{x}/{y}.png?access_token=pk.eyJ1Ijoic2xhIiwiYSI6Ik15dE1uclUifQ.ZmSBZxWOZYCSW3m71abSzQ#17',
          type: 'xyz'
        }
      }    

        $scope.map = {
          defaults: {
            layers: {
              baselayers: {
                basemap: $scope.basemapLayers.basemap,              
                map2007: $scope.basemapLayers.map2007,
                map1998: $scope.basemapLayers.map1998,
                map1988: $scope.basemapLayers.map1988,
                map1975: $scope.basemapLayers.map1975,
                map1969: $scope.basemapLayers.map1969,
                map1955: $scope.basemapLayers.map1955
              }
            }            
          },
           center: {
            lat: 1.355,
            lng: 103.840, 
            zoom: 14,
            minZoom: 12,
            maxZoom: 18,
            zoomControlPosition: 'topleft'
                },
          markers : {},
          events: {
            map: {
              enable: ['context'],
              logic: 'emit'
            }
          }
        };

        //$scope.goTo(0);
        $scope.locate();

        $scope.map2 = {
          defaults: {
            layers: {
              baselayers: {
                map1955: $scope.basemapLayers.map1955,
                map1969: $scope.basemapLayers.map1969,
                map1975: $scope.basemapLayers.map1975,
                map1988: $scope.basemapLayers.map1988,
                map1998: $scope.basemapLayers.map1998,
                map2007: $scope.basemapLayers.map2007,
                basemap: $scope.basemapLayers.basemap
              }
            }            
          },
           center: {
            lat: 1.355,
            lng: 103.840, 
            zoom: 14,
            minZoom: 12,
            maxZoom: 18,
            zoomControlPosition: 'topleft'
                },
          markers : {},
          events: {
            map: {
              enable: ['context'],
              logic: 'emit'
            }
          }
        };

        //$scope.goTo(0);
        $scope.locate();

      });

      var Location = function() {
        if ( !(this instanceof Location) ) return new Location();
        this.lat  = "";
        this.lng  = "";
        this.name = "";
      };

      $ionicModal.fromTemplateUrl('templates/addLocation.html', {
        scope: $scope,
        animation: 'slide-in-up'
      }).then(function(modal) {
          $scope.modal = modal;
        });

      /**
       * Detect user long-pressing on map to add new location
       */
      $scope.$on('leafletDirectiveMap.contextmenu', function(event, locationEvent){
        $scope.newLocation = new Location();
        $scope.newLocation.lat = locationEvent.leafletEvent.latlng.lat;
        $scope.newLocation.lng = locationEvent.leafletEvent.latlng.lng;
        $scope.modal.show();
      });

      $scope.saveLocation = function() {
        LocationsService.savedLocations.push($scope.newLocation);
        $scope.modal.hide();
        $scope.goTo(LocationsService.savedLocations.length - 1);
      };

      /**
       * Center map on specific saved location
       * @param locationKey
       */
      $scope.goTo = function(locationKey) {

        var location = LocationsService.savedLocations[locationKey];

        $scope.map.center  = {
          lat : location.lat,
          lng : location.lng,
          zoom : 14
        };

        $scope.map.markers[locationKey] = {
          lat:location.lat,
          lng:location.lng,
          message: location.name,
          focus: true,
          draggable: false
        };

      };

      $scope.goToMapYear = function(histmap) {

        var mapyear = HistoricalMapService.locateMapYear[histmap];

      };

      /**
       * Center map on user's current position
       */
      $scope.locate = function(){

        $cordovaGeolocation
          .getCurrentPosition()
          .then(function (position) {
            $scope.map.center.lat  = position.coords.latitude;
            $scope.map.center.lng = position.coords.longitude;
            $scope.map.center.zoom = 15;

            $scope.map.markers.now = {
              lat:position.coords.latitude,
              lng:position.coords.longitude,
              message: "You Are Here",
              focus: true,
              draggable: false
            };

          }, function(err) {
            // error
            console.log("Location error!");
            console.log(err);
          });

      };

    }]);

Display map in map.html without using menu.html:

<ion-view title="OneMap">

  <ion-nav-buttons side="left">
    <button menu-toggle="left" class="button button-icon icon ion-navicon"></button>
  </ion-nav-buttons>

  <ion-nav-buttons side="right">
    <button ng-click="locate();" title="Search" class="button button-icon icon ion-ios-search-strong"></button>
  </ion-nav-buttons>

<div class="row">

    <ion-content data-tap-disabled="true" class="col col-50">

        <leaflet id="map1" event-broadcast="map.defaults.events" defaults="map.defaults" center="map.center" markers="map.markers" layers="map.defaults.layers" width="100%" height="100%" ng-if="map"></leaflet>

    </ion-content>

    <ion-content data-tap-disabled="true" class="col col-50" style="left: 50%;">

        <leaflet id="map2" event-broadcast="map.defaults.events" defaults="map.defaults" center="map.center" markers="map.markers" layers="map2.defaults.layers" width="100%" height="100%" ng-if="map2"></leaflet>

    </ion-content>

</div>

  <ion-tabs id="actionTabs" class="tabs-positive tabs-icon-top">

    <a ng-click="locate();" name="Find Me" class="button button-icon icon ion-pinpoint" style="color: white;"></button>

</ion-tab>

</ion-tabs>

</ion-view>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is there a way to conceal the loading screen until the website has completely loaded?

I've been working on my personal portfolio/website and encountered a bug that I can't seem to fix on my own. The issue is with the logo (aa) and text under it showing even after the content page has fully loaded, taking around 3 seconds to hide. ...

Controlling multiple bx-sliders with a single pager using only JavaScript

Is there a way to control 3 sliders using the same pager? I attempted to use the following code but it did not work: <script language="javascript"> $('.mobile_left_mble,.mobile_right_mble,.text_btn').bxSlider({ //pagerCustom: '#bx- ...

When a custom icon is clicked in the vue-select dropdown, the custom method is not activated

In my current project, I am creating a vue-component based on vue-select. Within this component, I have added a custom info Icon. The issue I am facing is that when the user clicks on the Icon, instead of triggering my custom method getInfo, it opens the s ...

Leveraging jQuery or javascript to display json data in a table with multiple columns

My goal is to convert a JSON data into an HTML table that dynamically creates columns based on the content of the JSON. However, I am facing challenges in looping through the JSON and rendering multiple columns when necessary. The desired output for the e ...

Invoking Ajax within a for loop

for (var i = 0; i < 5; i++) { using (x = new XMLHttpRequest()) sendRequest("GET","d.php?id=" + i), checkResponse(null), updateStatus = function() { if (x.state == 4 && x.responseCode == 200) notifyUser(i); } } My goal now is to e ...

The error message "Cannot read property 'properties' of undefined" is being thrown by the leaflet-search plugin

I attempted to implement the leaflet-search feature using a Vue-cli component. However, when I initiate a search, I encounter the following error message specifically related to the leaflet search function: Uncaught TypeError: Cannot read property &apo ...

Building a family tree with JavaScript's Document Object Model

My goal is to use jQuery to construct the following DOM setup: <li> <label> user <input type=radio> </label> </li> Below is the jQuery code I am trying to use. $('<input>') .attr({type:'radio&ap ...

External function does not support jQuery types

In my theme.js file, I currently have the following code: jQuery(function ($) { accordion($) }) const accordion = ($) => ... By placing the accordion function directly into the jQuery function, Typescript is able to assist with the installed jquery ...

Toggle the visibility of a div by clicking on another div in a

I have created a unique design where a div features a background image of a face, along with a paragraph, two buttons, and an input box inside it. While I know this question has been asked before, my scenario is slightly different. I want the div with the ...

Expanding div width with jQuery as a percentage

Currently, I am facing a dilemma as I try to devise an equation for expanding the width of a div based on its current height. The Scenario Within this situation, there is a div that features a background image set to "contain." The original background ima ...

Determine the height using jQuery before adding the class

I've been grappling with jQuery to accurately calculate the height of an element and then apply a specific CSS class to adjust its height. The issue I'm facing is that jQuery seems to be executing these calculations out of order, which is causing ...

Having trouble with overriding an @media query for material-ui react components?

I've been trying to modify a @media CSS rule on a Material UI component, similar to the discussions on How to over-ride an @media css for a material-ui react component and Override components like MuiTab that use media queries. However, I have not bee ...

Achieving both vertical and horizontal center alignment specifically for mobile devices

Is there a way to center a column on mobile devices only while maintaining a fixed height for the section? <div class="" style="background-image: url(image url;); background-position: right bottom; background-size: cover; height: 462px;"> <div cl ...

Continuously running React useEffect even with an empty dependency array

In my React application, I have implemented a hook system. Each sub-hook that is generated within this main hook is assigned a unique ID automatically. This ID is incremented by 1 every time a new sub-hook is created, ensuring uniqueness. const App = ...

Updating the appearance of a non-declared HTML child component on-the-fly using Angular

Trying to dynamically adjust the style of an unspecified div is causing some trouble. Using Angular and PrimeNG, invisible divs are being generated that I cannot access through inline styles. The objective is to allow a user to input a width as a string (5 ...

Trying to retrieve JSON data from an API in VueJS and successfully logging the results, but struggling to render the data on the page. (I

Having recently transitioned from React to VueJs, I encountered a problem where fetching data using axios.get returns a successful response in the console.log. However, when trying to iterate through the array with v-for, nothing is rendered. If you have a ...

Tips for saving and editing a file with JavaScript

I need a website visitor to input text into a text area on my site. When they submit the form, I want the entered text to be saved in a .txt file located in the same directory as the current web page. I am unsure of how this can be accomplished, and if i ...

What is the best way to ensure that a React app is always displayed in full screen

I am facing an issue while developing an app with React and Material UI. I am trying to display the app in full-page mode, but unable to achieve it successfully. Currently, it appears like this: https://i.sstatic.net/Hg0CA.png Here is my code snippet from ...

Tips on updating a specific value within an element stored in an array

I'm currently in the process of setting up a table where each row contains unique values. Using a for loop, I am able to generate these rows and store them in an array. Now, my question arises when I consider modifying a particular value with the id " ...

Unable to access $_POST parameters in PHP when making an Ajax request

My HTML file is shown below: <script> var xml = new XMLHttpRequest(); xml.onreadystatechange = function(){ if (xml.readyState === 4 && xml.status === 200) { console.log(xml.responseText); } } xml ...