Skip to content

Commit

Permalink
add addon component registration and more docs
Browse files Browse the repository at this point in the history
  • Loading branch information
miguelcobain committed Mar 8, 2019
1 parent 8c45178 commit 3591a4a
Show file tree
Hide file tree
Showing 10 changed files with 188 additions and 6 deletions.
3 changes: 3 additions & 0 deletions addon/components/leaflet-map.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
merge as emberMerge,
assign as emberAssign
} from '@ember/polyfills';
import { inject as service } from '@ember/service';
import BaseLayer from 'ember-leaflet/components/base-layer';
import { ParentMixin } from 'ember-composability-tools';
import toLatLng from 'ember-leaflet/macros/to-lat-lng';
Expand All @@ -13,6 +14,8 @@ export default BaseLayer.extend(ParentMixin, {
tagName: 'div',
layout,

emberLeaflet: service(),

leafletOptions: Object.freeze([
// Map state options
'center', 'zoom', 'minZoom', 'maxZoom', 'maxBounds', 'crs',
Expand Down
10 changes: 10 additions & 0 deletions addon/helpers/ember-leaflet-assign-to.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { helper } from '@ember/component/helper';

export function emberLeafletAssignTo([object], { key, value, onChange }) {
object[key] = value;

// we need to send out the assigned object because ember freezes helper arguments
onChange(object);
}

export default helper(emberLeafletAssignTo);
23 changes: 23 additions & 0 deletions addon/services/ember-leaflet.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import Service from '@ember/service';
import { assert } from '@ember/debug';

export default Service.extend({

init() {
this._super(...arguments);
this.set('components', []);
},

registerComponent(name, options = {}) {
let components = this.get('components');
let as = options.as || name;

assert(
`Tried to register component \`${name}\` as \`${as}\`, but it was already registered. Try to register a different component or register it under a different name.`,
components.find((c) => c.name === name || c.as === as) === undefined
);

components.push({ name, as });
}

});
19 changes: 17 additions & 2 deletions addon/templates/current/leaflet-map.hbs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{{yield (hash
{{#with (hash
tile=(component "tile-layer" parentComponent=this)
wms-tile=(component "wms-tile-layer" parentComponent=this)
marker=(component "marker-layer" parentComponent=this)
Expand All @@ -12,7 +12,22 @@

wmsTile=(component "wms-tile-layer" parentComponent=this)
geoJSON=(component "geojson-layer" parentComponent=this)
)}}
) as |components|}}

{{!--
Here we need to create the addon registered contextual components to yield later
--}}
{{#each emberLeaflet.components as |c|}}
{{ember-leaflet-assign-to
components
key=c.as
value=(component c.name parentComponent=this)
onChange=(action (mut mergedComponents))}}
{{/each}}

{{yield mergedComponents}}
{{/with}}

{{!--
`wmsTile` and `geoJSON` are provided for backwards compatibility reasons.
Contextual component names should have the same name as non-contextuals
Expand Down
1 change: 1 addition & 0 deletions app/helpers/ember-leaflet-assign-to.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default, emberLeafletAssignTo } from 'ember-leaflet/helpers/ember-leaflet-assign-to';
1 change: 1 addition & 0 deletions app/services/ember-leaflet.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from 'ember-leaflet/services/ember-leaflet';
28 changes: 28 additions & 0 deletions tests/dummy/app/pods/docs/addons/controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// BEGIN-SNIPPET marker-cluster.js
import Controller from '@ember/controller';

// NOTE: this example uses ember-decorators and native classes
export default class MarkerClusterController extends Controller {
lat = 40.713473;
lng = -74.007038;
zoom = 18;

markers = [
{
title: 'TD Bank',
description: '258 Broadway, New York, NY 10007, EUA',
location: [40.713687, -74.007068]
},
{
title: 'City Hall',
description: 'New York, NY 10007',
location: [40.713545, -74.006707]
},
{
title: 'Chase Bank',
description: '253 Broadway, New York, NY 10007, EUA',
location: [40.713316, -74.007386]
},
];
}
// END-SNIPPET
84 changes: 81 additions & 3 deletions tests/dummy/app/pods/docs/addons/template.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,89 @@
# Addons

Just as Leaflet has many plugins, ember-leaflet also does. The community created ember addons that extend ember-leaflet
functionality, usually using some Leaflet plugin under the hood. A list of those addons can be found
Leaflet has many plugins and they provide very useful features for your maps.
To use them in ember-leaflet, the community created ember addons that extend ember-leaflet
functionality, usually using some of those Leaflet plugins under the hood. A list of those addons can be found
in the {{#docs-link "addons"}}addons page{{/docs-link}}.

As an example, let's take `ember-leaflet-marker-cluster` addon.
## Using an addon

As an example, let's take `ember-leaflet-marker-cluster` addon. You can install it by running:

```bash
ember install ember-leaflet-marker-cluster
```

This addon will register a new `<layers.marker-cluster>` component and you can use it like:

{{#docs-demo as |demo|}}
{{#demo.example name="marker-cluster.hbs"}}
<LeafletMap @lat={{lat}} @lng={{lng}} @zoom={{zoom}} as |layers|>

<layers.tile @url="https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png"/>

<layers.marker-cluster as |cluster|>
{{#each markers as |m|}}
<cluster.marker @location={{m.location}} as |marker|>
<marker.popup>
<h3>{{m.title}}</h3>
{{m.description}}
</marker.popup>
</cluster.marker>
{{/each}}
</layers.marker-cluster>

</LeafletMap>
{{/demo.example}}

{{demo.snippet "marker-cluster.hbs"}}
{{demo.snippet "marker-cluster.js"}}
{{/docs-demo}}

## Creating an addon

### Showing up on ember-leaflet addons page

The ember-leaflet {{#docs-link "addons"}}addons page{{/docs-link}} automatically fetches npm packages that meet
these criteria:

1. the package name must start with `ember-leaflet-`
2. it must contain the `ember-leaflet` keyword on the `package.json` file
3. the link to the repository should be correctly filled in on the `package.json` file

### Integration with `<LeafletMap>` component

It is very common for addons to add new kinds of layers, like we've just seen with
`ember-leaflet-marker-cluster`. In order for `<LeafletMap>` component to yield your custom component
you need to register it on the included ember-leaflet service in an instance initializer.

Here is an example of the instance initializer that `ember-leaflet-marker-cluster` uses
to register its `marker-cluster` component:

```js
// addon/instance-initializers/register-component.js
export function initialize(appInstance) {
// first we lookup the ember leaflet service
let emberLeafletService = appInstance.lookup('service:ember-leaflet');

// to support older versions of ember-leaflet that do not include the service, we add a guard here
if (emberLeafletService) {
// we then invoke the `registerComponent` method
emberLeafletService.registerComponent('marker-cluster-layer', { as: 'marker-cluster' });
}
}

export default {
initialize
};
```

The `registerComponent` method accepts two arguments:
- the component name
- an options object. Only the `as` option is supported at the moment. The `as` option is the name
under which the component will yielded as from the `<LeafletMap>` component.

### Including the leaflet plugin

Your addon should be responsible for including the necessary leaflet plugin, either using
[ember-auto-import](https://github.com/ef4/ember-auto-import) or importing it by customizing your `index.js` file.
Please user other ember-leaflet addons as a reference.
1 change: 0 additions & 1 deletion tests/dummy/public/_redirects

This file was deleted.

24 changes: 24 additions & 0 deletions tests/integration/helpers/ember-leaflet-assign-to-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';

module('Integration | Helper | ember-leaflet-assign-to', function(hooks) {
setupRenderingTest(hooks);

test('it assigns a value to an existing object', async function(assert) {
await render(hbs`
{{#with (hash key1="value1") as |obj|}}
{{ember-leaflet-assign-to obj key="key2" value="value2" onChange=(action (mut merged))}}
{{#each-in merged as |k v|}}
<p>{{k}} {{v}}</p>
{{/each-in}}
{{/with}}
`);

assert.dom('p').exists({ count: 2 });
assert.dom('p:nth-child(1)').hasText('key1 value1');
assert.dom('p:nth-child(2)').hasText('key2 value2');
});
});

0 comments on commit 3591a4a

Please sign in to comment.