Skip to content

TopicComponent

andy.rothwell edited this page Oct 4, 2018 · 10 revisions

TopicComponent

NOTE: this component type should be renamed now that we have made being included in a topic optional for any component. This is issue 5.

All components have the mixin "TopicComponent" which adds a set of props to each of them:

prop definition or description
slots
options
item

It also adds the function evaluateSlot() to each component in the library.

By mixing this into all components, all templates, functions, computeds, and other things in the components can fairly uniformly be written to use these props and the evaluateSlot() function.

In other components

Because this is mixed in, any component will automatically have objects in their props called "slots", "options", and "item".

If the component was included as part of a TopicComponentGroup, these props objects will be filled out with the values provided to the TopicComponentGroup, because the TopicComponentGroup template includes the following:

<component v-for="(comp, compIndex) in topicComponents"
           :is="comp.type"
           class="topic-component"
           :slots="comp.slots"
           :options="comp.options"
           :item="item"
           :key="getCompKey(key, compIndex)"
/>

In a Mapboard config file

When you create an array of components in a config file, you can include objects as "slots", "options", and "item" parameters of any component, and they will become the props of the component. For instance, to add text to a callout, create a slots object, and create a parameter called "text" inside of the slots:

components: [
  {
    type: 'callout',
    slots: {
      text: '\
        Property assessment and sale information for this address. Source: Office of Property Assessments (OPA). OPA was formerly a part of the Bureau of Revision of Taxes (BRT) and some City records may still use that name.\
      '
    }
  },

evaluateSlot()

If a component will display (or somehow otherwise require) data from the state or from an item, this information cannot be provided to the component until the app is running and the data has been retrieved.

In such a case, instead of passing a value to the component as an option, you can pass a function to the component as a slot.

Any component can, in the place of a value, place "evaluateSlot(slots.value)"

For instance, the template for Badge looks like this:

<div class="mb-badge panel center">
  <div class="mb-badge-header" :style="style">
    {{ evaluateSlot(slots.title) }}
  </div>
  <div class="mb-badge-body">
    <h1>{{ evaluateSlot(slots.value) }}</h1>
    <strong>{{ evaluateSlot(slots.description) }}</strong>
  </div>
</div>

The config for a badge could therefore look like this:

{
 type: 'badge',
 slots: {
   title: 'Vacancy',
   value: function(state) {
     return state.sources.vacancy.status;
   },
    description: function(state) {
      var code = state.geocode.data.properties.zoning;
      return ZONING_CODE_MAP[code];
    },
 }
},

The functions provided for "value" and "description" are passed directly into the evaluateSlot() function, which, when it runs has access to the contemporary app state.

Clone this wiki locally