Warning: The magic method SFML_Singleton::__wakeup() must have public visibility in /home/public/wp-content/plugins/sf-move-login/inc/classes/class-sfml-singleton.php on line 72

Warning: Cannot modify header information - headers already sent by (output started at /home/public/wp-content/plugins/sf-move-login/inc/classes/class-sfml-singleton.php:72) in /home/public/wp-includes/feed-rss2.php on line 8
vue – Thoughts, etc. https://www.munderwood.ca Tracking the occasional random walk Thu, 25 Apr 2019 18:08:05 +0000 en-CA hourly 1 https://wordpress.org/?v=5.7.2 https://www.munderwood.ca/wp-content/uploads/2016/03/photo-150x150.jpg vue – Thoughts, etc. https://www.munderwood.ca 32 32 Measuring distances on Leaflet maps in Vue applications https://www.munderwood.ca/index.php/2019/04/25/measuring-distances-on-leaflet-maps-in-vue/ https://www.munderwood.ca/index.php/2019/04/25/measuring-distances-on-leaflet-maps-in-vue/#comments Thu, 25 Apr 2019 18:08:05 +0000 http://www.munderwood.ca/?p=279 [Read more...]]]> Vue2Leaflet is a great library that provides a very straightforward approach to using Leaflet maps in Vue applications. Leaflet.PolylineMeasure is a great Leaflet plugin that adds a tool to allow the user to measure distances along (poly)lines by drawing them on top of the map.

Today I released the initial version of a Vue2Leaflet plugin to provide a simple wrapper of the polyline measurement tool as a Vue2Leaflet plugin, via the vue2-leaflet-polyline-measure component. Usage is simple:

<l-map>
  <l-polyline-measure :options="{ showUnitControl: true }" position="bottomright"/>
  <!-- other map components -->
</l-map>

The options  object is passed directly to the underlying library, so can be any of the polyline measurement options. The position  parameter places the control in a corner of the map based on the available Leaflet control options.

]]>
https://www.munderwood.ca/index.php/2019/04/25/measuring-distances-on-leaflet-maps-in-vue/feed/ 2
Adding Vue reactivity to js-data relationships https://www.munderwood.ca/index.php/2018/05/16/adding-vue-reactivity-to-js-data-relationships/ https://www.munderwood.ca/index.php/2018/05/16/adding-vue-reactivity-to-js-data-relationships/#comments Wed, 16 May 2018 18:30:25 +0000 http://www.munderwood.ca/?p=256 [Read more...]]]> While attempting to have Vue components react to changes in my js-data model instances and their relationships, I found a great post from Caleb Roseland with an accompanying code example. They detail how to make model properties reactive in Vue, without overriding js-data’s own reactivity. What they don’t discuss is how to make Vue react to changes in the set of models associated with another through a relationship.

For example, if you have a Post that hasMany Comments, and a component on your page that iterates over post.comments , then the comments list still won’t change in Vue when it does in js-data.

Summary / tl;dr

By adding a boolean option to specify that some js-data relations should be made reactive, and defining a  VueReactiveRecord class that enables Vue reactivity on those relations, we can use related models in a Vue template and have them update when the data store changes. Check out this gist to see an example of the final result.

Making relationships reactive

My first attempt was to hew as closely to Caleb’s example as possible, automatically discovering every relationship and making them all reactive. Unfortunately the resulted in neither side of the relationship working correctly. Even though a post  and some associated comment  records were in the store, post.comments  was empty as was each comment.post . At first I wondered if there would be an infinite loop problem, of A reacting to B reacting to A reacting to B reacting … . Instead it appeared as if neither side was able to react even once, and the models were never connected to each other. Either way, I didn’t debug that issue and instead set up a method by which relationships would only become reactive if explicitly told to do so.

Opting in

When defining the js-data mappers, I included a new optional property named vueReactive  to the relationships that I explicitly wanted to make reactive within Vue components. For example, it’s much more likely that a new comment will be added to an existing post than that the post a comment was for will become a different one, so we can specify that the hasMany from posts to comments should be reactive, but leave the belongsTo  from comments to posts alone:

defineMapper('post', ...
  ...
  relations: {
    hasMany: {
      comment: {
        foreignKey: 'post_id',
        localField: 'comments',
        vueReactive: true,
      },
    },
  },
);

With that in place, I updated Caleb’s  ViewReactiveRecord class:

class ViewReactiveRecord extends Record {
  ...
  // Add Vue reactivity to relationships as well, when their definitions say to.
  const relationsByType = this._mapper().relations;
  // e.g. relationsByType = { hasMany: {...}, belongsTo: {...} }
  for (const relType in relationsByType) {
    const relations = relationsByType[relType];
    // e.g. relations is all hasMany relationships, or all belongsTo ones.
    for (const relName in relations) {
      const relation = relations[relName];
      // Now relation is the actual definition of a single relationship on the mapper
      if (!relation.vueReactive) { continue; }
      const key = relation.localField;
      Vue.util.defineReactive(this, key, this[key]);
    }
  }
  ...
}

Using the reactive relationships

Now we can have a Vue template that does something such as this:

<div>
  <h1>{{ user.name }}</h1>
  <h2>Post titles</h2>
  <p v-for="post in user.posts" :key="post.id">
    {{ post.title }}
  </p>
</div>

and know that if the set of associated posts in the js-data store changes, the list of titles displayed will reactively update accordingly.

 

]]>
https://www.munderwood.ca/index.php/2018/05/16/adding-vue-reactivity-to-js-data-relationships/feed/ 3