0

Beginner here, having trouble resizing a leaflet map after a CSS change via KnockoutJS.

The idea is to make 250px room on the left side for a sidebar whenever a button on the topbar is pressed (and triggers the toggleSidebar function in my JS).

My problem is that the map does not change size.

I have a leaflet map:

    <div id="map-container" data-bind="css: sidebarVisible">
        <div id="map"></div>
    </div>

the following CSS:

html,
body {
    font-family: Arial, sans-serif;
    height: 100%;
    margin: 0;
    padding: 0;
}

.wrapper {
    display: flex;
    width: 100%;
    height: 600px;
}

#map {
    height: 100%;
    width: 100%;
}

#map-container {
    position: absolute;
    top: 40px;
    height: calc(100% - 40px);
    width: 100%;
}

#map-container.moveForSidebar {
    left: 250px;
    width: calc(100% - 250px);
}

and the following JS:

// Create Map
var map = L.map('map').setView([52.518611, 13.376111], 14);

layer = L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoidHJpcGxlIiwiYSI6ImNqaW9nbXVpYzBiNjUza3FlaWJqbno2aXQifQ.gZIoqCkam1hIriIj3Mr-lw', {
    maxZoom: 18,
    attribution: 'Map data &copy; <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, ' +
        '<a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, ' +
        'Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
    id: 'mapbox.streets'
});

layer.addTo(map);

// Toogle Sidebar Functionality
this.visibilityToggle = ko.observable(true);

this.sidebarVisible = ko.pureComputed(function() {
    return self.visibilityToggle() ? "moveForSidebar" : "";
}, ViewModel);

this.toggleSidebar = function() {
    self.visibilityToggle = !self.visibilityToggle;
    console.log(self.visibilityToggle);
    map.invalidateSize();
};

Manually changing visibilityToggle and refreshing the page actually shows the map the way I want it to. However changing it via the function and calling invalidateSize does not.

This question seemed similar and he seems to be using the same function to resize his map. I also tried adding the Timeout as he has done, but as expected it didn't help.

Would highly appreciate any help, this has been driving me nuts for the last few hours :/

ceik
  • 33
  • 5
  • I don't know if this is your only issue, but in your toggleSidebar function you're overwriting the visibilityToggle observable instead of settings its value. It should look like `self.visibilityToggle(!self.visibilityToggle());` – Jason Spake Jun 21 '18 at 22:57
  • @JasonSpake Yes, this did the trick, thanks so much! (Happy to accept it as answer if you post it) – ceik Jun 22 '18 at 09:07
  • Awesome I'm glad that did it – Jason Spake Jun 22 '18 at 15:54

1 Answers1

0

In your toggleSidebar function you're overwriting the visibilityToggle observable instead of settings its value. It should look like

self.visibilityToggle(!self.visibilityToggle());

reference: http://knockoutjs.com/documentation/observables.html

Not all browsers support JavaScript getters and setters (* cough * IE * cough *), so for compatibility, ko.observable objects are actually functions.

  • To read the observable’s current value, just call the observable with no parameters. In this example, myViewModel.personName() will return 'Bob', and myViewModel.personAge() will return 123.

  • To write a new value to the observable, call the observable and pass the new value as a parameter. For example, calling myViewModel.personName('Mary') will change the name value to 'Mary'.

Jason Spake
  • 4,293
  • 2
  • 14
  • 22