VueJS watchers for MomentJS

It took me some time to figure out what’s been going wrong with the watchers working on datepicker integration for CakePHP-Calendar plugin.

Problem domain:

On loading modal window for creating calendar event, one of the dropdowns pass default start/end time for the event interval (start/end dates). This config object is passed to as a property into interval component that contains two child datepicker components.

Whenever the config property changes, it adjusts startMoment and endMoment objects and passes them into datepickers. The change is monitored via watch functionality of VueJS.

Example:

Vue.component('interval-holder', {
    template: `<div>
        <datepicker :date-moment="startMoment"></datepicker>
        <datepicker :date-moment="endMoment"></datepicker>
    </div>`,
    props: ['config', 'initialMoment'],
    data: function() {
        return {
            startMoment: null,
            endMoment: null
        };
    },
    watch: {
        config: function() {
            this.startMoment = this.initialMoment;
            this.startMoment.set({'hour': this.config.start.hour, 'minute': this.config.start.min});
            
            this.endMoment = this.initialMoment; 
            this.endMoment.set({'hour': this.config.end.hour, 'minute': this.config.end.min});
        }
    }
});

Vue.component('datepicker', {
    // value var is useless here, as we use daterangepicker from jQuery 🙁
    template: `<div>
        <input type="text" :value="value"/>
    </div>`,
    props: ['dateMoment'],
    mounted: function() {
        var self = this;
        //load jquery bootstrap-datepicker instance
        this.instance = $(this.$el).find('input').daterangepicker().data('daterangepicker');
        
        $(this.$el).find('input').on('apply.daterangepicker', function(ev, picker) {
            self.momentObject = picker.startDate;
            self.value = picker.startDate.format('YYYY-MM-DD HH:mm');
        });
    },
    data: function() {
        return {
            instance:null,
            value: null,
            momentObject: null,
        };
    },
    watch: {
        dateMoment: function() {
            this.momentObject = this.dateMoment;
            this.value = this.momentObject.format('YYYY-MM-DD HH:mm');
        },
    }
});

If we set hours and minutes the following way as in the example above, dateMoment watcher won’t catch the change. According to the docs, it’s adviced to use deep param:

To also detect nested value changes inside Objects, you need to pass in deep: true in the options argument. Note that you don’t need to do so to listen for Array mutations.

watch: {
    dateMoment: {
        handler: function(val, old) {
            console.log('dateMoment changed');
        },
        deep: true
    }
}

Still no luck. Apparently, MomentJS object “too deep”. The only way to get it working ended up like this, change the parent component moment objects assignment, keeping the child-component watch function unchanged.

watch: {
    config: function() {
        var newStart = moment(this.startMoment);
        newStart.set({'hour': .., 'minute': ..});
        this.startMoment = newStart;
        
        //create a new instance of newEnd and assigning it to this.endMoment
        // get the dateMoment observe the change.
        // Ugly? Yes. Working? Yes..
    }
}

If anyone has a better (more elegant) way to fix this issue – welcome in the comments section! 🙂

 

ES2015: Refresher on modern JavaScript

A quick lookup on modern JavaScript and whole Babel thing. This will be a start of a small research on splitting frontend and backend implementation for CakePHP framework and its plugin.

JavaScript – technological singularity & younglings effect

On March 2017, Eugene Gusev had an interesting talk (in Russian) at HolyJS regarding the technological singularity as whole in Front-End, and JavaScript ecosystem in particular. As a thesis taken, he noted an enormous number of 350k packages in NPM.

Few points being stated over the talk:

  • Quality of the packages (aka younglings publish low quality tools)
  • Hype over the ecosystem (frameworks and libs go up and down in popularity scale).
  • Business forces the choice, leaving minimum time on technical decision-making process.
  • Stop writing code, or “stop publishing your code”.
  • In order to program you should be a computer scientist.

All the points are quiet controversial. Though, accepting some of these statements as a potential problem, most of them have a reasonable explanation.

Prelude

Back when the trees were tall and the grass was green, I graduated my BSc in Computer Science, I’ve started working as a Junior Web Developer. By that time, a programmer who knew only JavaScript, or solely was coding on Perl/PHP/Python was considered lazy/unemployed/unicorn. The time flew by and the industry started splitting technological stack, so from Programmer/SysAdmin we forked into Front/Backend developers, SysAdmins to DevOps etc.

University, really?

We still have certain professions that require an educational degree. By paying for your education, you’re prompted to access research laboratories, expensive equipment that’s required for your research. Think of physicists or chemists. Stating that diploma (for Computer Science) somehow justifies your profile, or what you should be doing for living left behind with the era of industrial revolution. “The spice must flow” – that’s where we get into the almighty Internet for self-education. Udemy, Coursera – it’s right there, most of it is free, just read it, learn it.

Technological Singularity

Technological singularity is a hypothesis that the invention of artificial superintelligence will abruptly trigger runaway technological growth, resulting in unfathomable changes to human civilization.

Are we there yet? Yes, we are. It just arrived silently. Clustering professions to narrow the specialization is one of the countermeasures to prevent the informational noise that we get once diving into IT-sector. That’s where we step into Hype effect.

Hype Effect

Hype Cycle diagram
Hype Cycle by Ember in the Real World

350 thousand package in NPM. That’s massive, but hold on a minute! CPAN didn’t have the same issue in Perl community? PEAR and Pecl repositories stacked by repetitive packages, written by people just because they could. And they did! Every year, some big player like Google, Facebook, name a few, presents a new approach towards a common problem. Angular, React, EmberJS, VueJS. It automatically triggers a hype.

Architects in the companies start massively migrating to trendy frameworks, as it’s backed up by one of the above companies, which promises stable development, stable versioning and ongoing support. We get a drastic shift of packages developed for these frameworks. And the story continues until something new arrives on the market.

As companies do not operate in vacuum, all these transitions correlate with business decisions. Packages appear in almost-ready-to-us state, and remain loosely maintained just to get your npm/phake/rake running smoothly during the deploy process.

Packages & Plugins flood

Slowly the picture of 350k packages come into place. Each of the packages is a reflection of a person behind it and the problem he or she was trying to solve. Good solutions become trendsetters itself, become community defacto standards. What happens with others? – Well, it’s a pure darwinism, which triggers professional boost among the developers.

To sum things up

Your knowledge derives from those who dared, and published something. If you cannot choose out of a hundred packages one or two that might fit in your application, maybe you should question yourself what exactly you trying to solve? Diversity of approaches in IT and its openness is our strength. You found something wrong, write a bugreport, or send a pull request. The rest is just excuses in most of the occasions!

Yarn: package manager for JS modules

Yarn kitty rocks!
Yarn kitty rocks!

Yarn is a package manager for your code. It allows you to use and share code with other developers from around the world. Yarn does this quickly, securely, and reliably so you don’t ever have to worry.

Yarn allows you to use other developers’ solutions to different problems, making it easier for you to develop your software. If you have problems, you can report issues or contribute back, and when the problem is fixed, you can use Yarn to keep it all up to date.

EmberJS: JCF with components

JavaScript Custom Form elements is a useful jQuery plugin for customising your form elements, in case you have to get away from the default styling of the form elements. However, there’s a tiny “but” with the plugin when you use it with EmberJS. JCF initially designed to be used on the global scope, and in some case (like mine), it’s not what you need.

If you’re using custom select-element with JCF without JCF.Scrollable, the list becomes unusable in few cases:

  1. It overflows the layout of the site
  2. Not keyboard-friendly, when you try to filter the options and not scroll till the end.
  3. When you use Ember addons like emberx-select, it doesn’t like custom data-attributes.

Eventually, using components concept of Ember, it’s easier to isolate the setups of JCF.

In my case, language options have only few options,where I prefer to wrap the native select options:

import Ember from 'ember';

export default Ember.Component.extend({
  cart: Ember.inject.service('shopping-cart'),

  didRender() {
    Ember.run.scheduleOnce('afterRender', function(){
      //#currency-options is the action <select>-element
      jcf.replace('#currency-options','Select', {
        "wrapNative": false,
        "wrapNativeOnMobile": true
      });
    });
  },

And, to avoid custom wrapping of dropdowns, for instance, country list, better to initiate JCF like this:

import Ember from 'ember';

export default Ember.Component.extend({
  classNames: ['input2','country-list'],
  didRender() {
    Ember.run.scheduleOnce('afterRender', function(){
      jcf.replace('#input2-select','Select');
    })
  }
});

Few more samples of the code, could be found in gist.

JavaScript: shooting yourself in the foot with configs once again

fef19aa014b44daee11603ce64525634a7fc79cc3cb7b81b3a413f3f178edbdc
Don’t be mainstream!

I’m not the only one blown away after digging up some of React/Redux boilerplate code. Great article proving some of my thoughts on the subject:

Copy-pasting configs from boilerplate projects always leads to hard-to-debug issues like this. It’s easy to miss somebody’s configuration decisions when you’re not the one making them. Don’t use boilerplate projects unless you understand each and every technology it uses!

I understand Dan’s frustration. But could we look at this from a different perspective? Don Norman’s The Design of Everyday Things teaches that there’s no such thing as “user error” — humans always make mistakes, and the failure to deal with these is on the product, not the user. How would we approach these user errors if we looked at them as design failures?

Yet another justification of “convention over configuration” and the reason of choosing EmberJS at the given time. Sorry React, not now, maybe a bit later.