DEV Community

Núria for codegram

Posted on • Originally published at codegram.com on

From Vue to Angular

Originally published at Codegram's blog

Everybody seems to be switching to Vue lately. There are tons of articles about migrating from React/Angular to Vue. Me? I’m doing quite the opposite. After working with Vue for about 2 years, switching to Angular is an interesting process.

I started working with Vue in late 2016, right when version 2.0 came out, and I’ve been using it as my frontend framework of choice almost exclusively. Before that, I had little experience with coding, just a bit of AngularJS, jQuery and vanilla JS. At the time there were not many resources to learn Vue, so I basically learned by reading the documentation. It was a really nice experience. Happy times.

A few months ago I started working at Codegram, where the front end framework of choice is Angular. I thought, hey, I have experience now, how hard can it be?

The learning curve


Well. Really hard.

Even if you’ve had years of experience working as a front-end developer, it is likely that you’ve only worked with HTML, JavaScript, and CSS. You might be familiar with the module system, and maybe you’ve used some build tools, like Gulp or Webpack.

When you start working with Vue, you can use just what you already know: HTML, JavaScript, and CSS. You could use Pug, TypeScript, and Stylus if you prefer any of those, but by default, you don’t need to learn anything else. Knowledge of Webpack helps, but the default configuration will work for most of the time.

Angular, on the other hand, imposes many things on you. In addition to the framework itself, that has a lot of concepts like modules, services, and so on, you also need to learn a new language (TypeScript) and RxJS.

True, TypeScript is more of a superset than an entirely new language, and if you are not working with a strict mode the type checking is mostly optional, but if you want to follow best practices, it adds quite a lot of overhead and slows down development a lot. I feel that a feature that with Vue I implemented in a breeze, with Angular takes much longer.

RxJS

RxJS is embedded in the way Angular works, so you need to follow a reactive programming pattern. I’ve come to really like RxJS, but I’ve had (and still have) a lot of trouble thinking reactive. It sure pays off, but imposing this on your framework can be a considerable stopper for people who don’t have experience with reactive programming. Also, sometimes these little graphs don’t help much:


I mean, come on

With Vue, usually, the component will automatically react to state changes without us having to worry about it. The component will be re-rendered, computed properties will be recalculated if needed, and so on. However, there are certain things that will require a manual trigger. Let’s say we need to execute some method every time a route parameter changes. With Vue we need to set a watcher like this:

watch: {
  '$route.params': function (params) {
    // do the thing
  }
}

With Angular and RxJS, route params is an observable so you can react to changes by tapping into the stream (or mapping, or any of the very cool RxJS operators)

this.route.params.pipe(
  tap(params => {
    // do the thing
  })
);

I like Angular’s reactive approach better, but I can understand that imposing RxJS is not a choice Vue should make for you. There is an official RxJS integration, which is something I’m looking forward to trying.

The template system

It surprised me that, even though Angular and Vue both use the same approach when working with templates (no JSX, just good old HTML with a few bindings and directives), the experience ends up being really different.

So, the things I needed to learn to work with Vue templates were just v-for, v-if (and v-else), v-bind:attribute (or the shorthand :attribute), v-on:event (or the shorthand @event). Basically, you need to append v- to whatever you want to do and it will work.

The things I’ve had to learn to work with Angular templates: *ngFor, *ngIf, [attribute], (event), some certain attributes work with [attr.whatever], there is also the [(banana-in-the-box)] for two-way binding (I must admit I love the name of that one, probably my favorite part about Angular so far). There is also [ngClass] and [ngStyle], which I know they are different from [class] or [style] but I can never seem to remember how or why.

Also, if you want to do an if/else structure, you need to add an extra ng-template and do something like:

<button *ngIf="someCondition; else otherBtn">
  An action
</button>
<ng-template #otherBtn>
  <button>
    Another action
  </button>
</ng-template>

And if you wanted to display a few items in each case without a wrapping element, you would need to first set the condition in a ng-container and then create two different ng-template. The condition is completely separated from the templates, making it much harder to read:

<ng-container
  *ngIf="someCondition; then templateA; else templateA">
</ng-container>

<ng-template #templateA>
  <p>Some text</p>
  <button>An action</button>
</ng-template>
<ng-template #templateA>
  <p>Some other text</p>
  <button>A different action</button>
</ng-template>

In Vue I find it way cleaner and easier to understand:

<button v-if="someCondition">
  An action
</button>
<button v-else>
  Another action
</button>

And if you don't want a wrapping element, just use the v-if in the template:

<template v-if="someCondition">
  <p>Some text</p>
  <button>An action</button>
<template v-else>
  <p>Some other text</p>
  <button>A different action</button>
</template>

I’m sure there is a reason why Angular works this way, and I’m not trying to suggest that it’s a bad framework, but when you’ve experienced Vue’s simple approach, even minor things like that can become a big pain point.


The general opinion, which I can share, is that Angular shines when working on huge projects and big teams. Angular already makes many decisions for you so the team can focus on what’s important. However, that’s something you can get with any other framework as well. Use TypeScript with Vue or React. Follow a style guide and folder structure (Vue ESLint and Nuxt can help you with that). Follow best practices. You can create a terrible project that doesn’t scale with Angular, just as you can with React or Vue. A framework won’t push you into bad patterns nor will save you from mistakes.

Vue is usually praised for creating a great dev experience, but in the end, the best framework is the one you are most comfortable with. I’m going to leave you with this slide by Evan Schultz, which accurately represents how I feel about Vue:

Top comments (4)

Collapse
 
johncarroll profile image
John Carroll

Not that this invalidates your point, but FYI this example

<ng-container
  *ngIf="someCondition; then templateA; else templateA">
</ng-container>

<ng-template #templateA>
  <p>Some text</p>
  <button>An action</button>
</ng-template>
<ng-template #templateA>
  <p>Some other text</p>
  <button>A different action</button>
</ng-template>

can be simplified to

<ng-container *ngIf="someCondition; else templateB">
  <p>Some text</p>
  <button>An action</button>
</ng-container>

<ng-template #templateB>
  <p>Some other text</p>
  <button>A different action</button>
</ng-template>

Or alternatively to

<ng-template [ngIf]="someCondition" [ngIfElse]="templateB">
  <p>Some text</p>
  <button>An action</button>
</ng-template>

<ng-template #templateB>
  <p>Some other text</p>
  <button>A different action</button>
</ng-template>

I don't have any experience with vue, how would the vue if/else example look if you had multiple if/else statements in the template? (i.e. how do you specify that a particular else statement pairs with an if statement?)

Collapse
 
codegram_user profile image
Codegram

Right! Thanks for your input.

In Vue, it's implied by the order of the blocks, the else needs to follow a v-if block (or v-else-if). So you would do something like this:

<template v-if="someCondition">
  <p>Some text</p>
  <button>An action</button>
</template>

<template v-else-if="someOtherCondition">
  <p>Some other text</p>
  <button>A different action</button>
</template>

<template v-else>
  <p>Another different text</p>
  <button>Another different action</button>
</template>

<template v-if="anotherSetOfConditions">
  <p>Some more text</p>
</template>

<template v-else>
  <p>Etc</p>
</template>

If you did something like this:

<div v-if="myCondition">
      Hello
</div>

<div>oops</div>

<div v-else>
      Bye
</div>

It would raise an error v-else used on element <div> without corresponding v-if.

Collapse
 
johncarroll profile image
John Carroll • Edited

Ah, well that's certainly intuitive! And that's definitely a better if/else syntax than what Angular has.

Again, not to invalidate the point of your article (but rather to explain why I think Angular is the way it is):

In Angular both ngIf and ngFor are simply standard structural directives which are shipped in CommonModule (and hence optional in an app). They rely on the same API that anyone can use to customize Angular. The limitations of that API (which is really pretty simple) are what create the wonky syntax. Personally, ngIf and ngFor (specifically) are so common that I think Angular would benefit if the framework gave them special treatment (which could improve the API for devs). Though I can see value in having complete consistency within the framework.

  • Edit I suppose making ngIf and ngFor special also might make them non-removable. And that would clash with Angular's goal of reducing the minimum framework size below 2kb (important for custom elements).

In Vue, is it possible to create a custom structural directive (or whatever Vue would call it) with similar functionality to v-if / v-else? e.g. is it possible to create a custom v-unless structural directive (which would also pair with v-else) for an app?

Thread Thread
 
codegram_user profile image
Codegram

Good to know, that's illuminating! :)

It is possible to create custom directives with Vue vuejs.org/v2/guide/custom-directiv... I never tried it, but since the hooks have access to the element el to manipulate the DOM, I guess you could create a simple v-unless that prevents it from rendering based on the binding.value. But it would be a standalone directive, I can't think of a way to pair it with an v-else or any other directive.