Category: jspm

AngularJS 1.5 Input Components

Introduction

The promise of JavaScript component-based architecture frameworks such as AngularJS 1.5, Angular 2, or Aurelia is enabling developers to write less code, both HTML markup, and JavaScript.  The ability to encapsulate HTML and JavaScript into reusable components should simplify the application consuming these components greatly.

Please, review this post and code, and then start your own component library for your applications. There are enough components here to get you started.  I have chosen to make these components granular with a single responsibility, rather that make a single component with many properties to change the behavior. This approach provides clean and readable HTML markup, clearly describing the components role and behavior.

This blog post and GitHub repo are written using ES6. I wrote why I use ES6 JavaScript here. I also leverage ES7 experimental class property features in my applications.

AngularJS 1.5 components are uncomplicated element directives. These components can encapsulate business logic and are testable.

If you have time, compare the amount of JavaScript code is required by Angular 2 components to the AngularJS 1.5 components. You’ll find that AngularJS 1.5 is simpler and currently requires considerably less framework code to register. You’ll also see that I separate the component registration from the component, this removes Angular from the component enabling very fast executing unit tests.  See the Review Presentation repo example.

The below images show the clean and minimal HTML required to produce a typical data form with comprehensive validation and associated messages, including password strength metrics. The “match” directive (see app.module.js) on the second input-password component handles comparing the two passwords. The corresponding error message is displayed below these components. The input control placeholder is included for instructional purposes only and is probably not needed in a simple form like this one.

html

form

References

I did my research before embarking on creating these input components. I’m very grateful to the many community authors for their blog posts and answers on StackOverflow. The below links helped me to understand this problem space and I recommend that you study them:

Creating a custom form field with validation using AngularJS 1.5 and TypeScript

Password Strength Meter

InputBaseComponent

The InputBaseComponent is the base class for the text input components. It exposes properties common to all HTML text input controls.

The InputBaseComponent creates the component label from the name attribute if the label attribute is not supplied. It’s onInit, onChange, and validate methods are invoked by deriving classes.

Normally an AngularJS 1.5 component does not update it’s parent model directly. As explained in the above blog post this component design calls for updating the model instead of using two-way bindings or a one-way binding with a corresponding event.

I agree with this architecture in this specific use case because it mimics the interaction that an input control would have if it was not encapsulated in a separate component. It is assumed that the form these components are hosted on would be adhering to the typical AngularJS component design pattern described in the AngularJS documentation.

By requiring the model in the component registration (see input-components.module.js), the model will be injected and is available to the component controller for reading and writing. When the view needs to be updated, $render is invoked and the below function updates the component value. When the component value is changed, the model value is set in the onChanage method.

COMPONENT REGISTRATION: 
require: {
    model: "ngModel"
}

ONINIT:
this.model.$render = () => {
  this.value = this.model.$viewValue;
}

ONCHANGE:
this.model.$setViewValue(this.value);

This base class handles setting sane values for the maximumLength and for setting  isRequired based on the minimumLength. The isRequired property is used in the HTML to set a required attribute.

The onChange method provides data input length validation by limiting the value length to the maximumLength.  This code is wrapped in try-catch block to provide a seam for logging an obvious attempt to hack your site. Remember, always defend in layers and never trust any data from the internet either on the client or server.

The validate method checks the input for minimum or maximum length validation rule violations. What is nice about this implementation is that the validation messages can easily be customized to provide the user with good information.  In this application, I’ve chosen to display the validation message next to the label.  If you don’t do this, then be sure to include the label in your validation message.

export default class InputBaseComponent {

  label;
  model;
  value;
  name;
  validationError;
  minimumLength;
  maximumLength;
  isRequired = false;

  constructor(StringUtility) {
    this.StringUtility = StringUtility;
    if(this.name && !this.label) {
      this.label = this.StringUtility.parseWords(this.name);
    }
  }

  onInit() {
    this.model.$render = () => {
      this.value = this.model.$viewValue;
    }
    if(!this.maximumLength) {
      this.maximumLength = 200;
    }
    if(this.minimumLength) {
      this.isRequired = true;
    }
  }

  onChange() {
    try {
      if(this.value && this.maximumLength && 
          this.value.length > this.maximumLength) {
        this.value = this.value.substring(0, this.maximumLength);
      }
    } catch(e) {
      this.value = '';
      // log this to your system as a security message
    }
    this.model.$setViewValue(this.value);
  }

  validate() {
    if(this.isRequired && this.minimumLength) {
      if(!this.value || this.value.length < this.minimumLength) {
        this.validationError = `has a minium length of ${this.minimumLength}`;
        return false;
      }
    }
    if(this.value && this.maximumLength && 
        this.value.length > this.maximumLength) {
      this.validationError = `has a maximum length of ${this.maximumLength}`;
      // log this to your system as a security message
      return false;
    }

    this.validationError = '';
    return true;
  }

}

InputBaseComponent.$inject = ['StringUtility'];

InputTextComponent

Now that we have all the hard work done, let’s extend InputBase and call the required methods.  For an input of type text, no additional validation is required.

import InputBase from '../input-base'

export default class InputTextComponent extends InputBase {

  constructor(StringUtility) {
    super(StringUtility);
  }

  $onInit() {
    super.onInit();
    super.validate();
  }

  onChange() {
    super.onChange();
    super.validate();
  }
}

InputTextComponent.$inject = ['StringUtility'];

InputEmailComponent

The InputEmailComponent extends the InputBase and adds email input validation. Notice that if the call to super validate returns false, this validation does not run.  You can change this logic to display all validation errors or display them one at a time as I do.

import InputBase from '../input-base'

export default class InputEmailComponent extends InputBase {

  constructor(StringUtility) {
    super(StringUtility);
  }

  $onInit() {
    super.onInit();
    this.validate();
  }

  onChange() {
    super.onChange();
    this.validate();
  }

  validate(){
    if(super.validate()) {
      if(this.value && 
          !this.StringUtility.isEmailValid(this.value)) {
        this.validationError = ' has invalid format';
        return;
      }
    }
  }
}

InputEmailComponent.$inject = ['StringUtility'];

InputTextComponent Template

This template has four groups:

  • input-group – apply CSS styles for spacing and alignment
  • form – subform container for the component
  • label-area – displays the label and associated validation messages
  • input – the input control

The validation messages are shown when:

  • the form control is invalid
  • and validation error text has a value
  • and
    • the control has been touched
    • or parent form has been submitted

You can choose when users see validation messages. I’ve used the above logic in my applications and users are happy with the experience.

<input-group>
  <ng-form name="{{vm.name}}Form">
    <label-area>
      <label for="{{vm.name}}">{{vm.label}}</label>
      <error-message ng-show="{{vm.name}}Form.{{vm.name}}.$invalid && 
        vm.validationError && 
        ({{vm.name}}Form.{{vm.name}}.$touched || 
        {{vm.name}}Form.$$parentForm.$submitted)">
          {{vm.validationError}}</error-message>
    </label-area>
    <input
      type="text"
      placeholder="{{vm.label | lowercase}}"
      autocomplete="off"
      ng-model-options="{allowInvalid: true, debounce: 250}"
      name="{{vm.name}}"
      id="{{vm.name}}"
      ng-model="vm.value"
      ng-change="vm.onChange()"
      ng-required="vm.isRequired"
      ng-minlength="vm.minimumLength"
      ng-maxlength="vm.maximumLength"
      maxlength="{{vm.maximumLength}}"
      >
    </input>
  </ng-form>
</input-group>

HTML Input Control

  • placeholder – optional.  I like, that I can bind the label and then use an Angular filter to change the label to lower case.
  • autocomplete – choose the option that meets your requirements
  • ng-model-options
    • allowInvalid – when true, allow ng-change to be raised on keystrokes when the control is invalid.
    • debounce – the time delay for model updating since the last keyboard input.
  • ng-model – binds to the component value
  • ng-change invokes the onChange method
  • ng-required – when true, sets the required attribute on the control
  • ng-minlength – sets the minimum length rule for the control
  • ng-maxlength – sets the maximum length rule for the control
  • maxlength – I STRONGLY urge you to ALWAYS set this attribute on any text input control.  Setting this attribute limits the number of characters that can be entered, pasted or dragged into the control at runtime. Remember that security is always in layers.

Form Submit Button Options

There are two schools of thought around form submit buttons.  One is to disable the submit button when the form is invalid, the other to allow the user to click the submit button and then show all input validation messages.

Your choice will depend on the application requirements and stakeholder choices.

The submit button strategy needs to take into account the applications timing of when to render validation messages.

I prefer to only show validation messages after the user visits the control or when the user submits the form and the control is invalid.

Thoughts

Whether you’re using AngularJS 1.5, Angular 2, Aurelia, et al., components provide the HTML and JavaScript developer a powerful programming paradigm that embraces separation of concerns, test ability, maintainability, readability, and are down right fun to work with.

Download

https://github.com/Oceanware/InputComponents

Close

Have a great day,

Just a grain of sand on the world’s beaches

Open Source – cave lupum

Introduction

I’ve been actively working with open-source JavaScript packages for about 18 months. Developers that are very generous with their time have built tools and frameworks that have enriched the lives of developers all over the world. I too have contributed tools and believe in this beautiful Ecosystem.

A few months ago I started to look under the hood of my SPA and Nodejs applications and found code and practices that caught my attention. I found packages that other packages depended on, have very few lines of code. Packages with dependencies that are out of date or dependencies that had warnings such as, this package version is subject to a denial of service attack.

Upon further reflection, I got very concerned about the damage a bad person could inflict on trusting developers that download packages that have a dependency that has been replaced by evil code. My system and software that I write could be compromised. Now imagine ticking time bomb code replicated over Docker Containers and placed on servers. Damage could be immeasurable.

cave lupum – Beware the wolf disguised as a lamb.

Publicly articulating details of the many attack scenarios I’ve thought of would be irresponsible. Instead, it’s time to start the conversation around the problem that our international community is currently faced with and how we can protect our precious open-source.

Again, this blog post is about getting the conversation started.

Over the last few weeks, I’ve met with high profile MVP’s and a few corporate executives that share similar quality and security concerns that I’m sharing in this blog post.

For the purpose of this blog post, “packages” refers to open-source JavaScript packages that are added to Nodejs, or JavaScript web applications using a package manager.

I’ll have a section down below for compiled downloads such as NuGet, Visual Studio Gallery, and the Visual Studio Marketplace.

Proposal Goals

  • Not add any burdens to the open-source developer
  • Provide package consumers a measured level of confidence in the package and its dependencies
  • Raise the quality of packages by having them evaluated
  • Have repositories provide evaluation services and reporting for their packages

Proposal

Package evaluation is performed in the cloud.  An MVP friend also thought about a command line tool that could be used locally.

Package evaluation should be opt-in.  Allow developers wanting their packages evaluated to submit their package for evaluation. An opt-in approach would not add any burdens to developers not wanting to participate, while at the same time, driving up quality for the packages that are evaluated, giving those developers additional credibility for their efforts.

Consumers of packages could choose to use evaluated packages or continue to use non-evaluated packages at their own risk.

Evaluation and Download

Where packages are evaluated (centralized vs. non-centralized) is a topic that will generate much discussion and debate.

Where evaluated packages are downloaded from (centralized vs. non-centralized) is another topic that will generate much discussion and debate.

Evaluation Metrics

A standard set of metrics is applied to JavaScript packages, yielding a consistent evaluation report, enabling consumers to easily compare packages.

Below is a short “starter list” of metrics. Additional metrics should include the warnings such as those that npm emits when packages are installed.

Most evaluation metrics are yes or no.  Some are numeric; others are a simple list. When a package is evaluated, all of its dependencies are also evaluated. A package’s evaluation can only be as good as its weakest dependency.

  • Package signed
  • Included software license
  • Number of dependencies
  • Number of dependencies with less than ten lines of JavaScript
  • Package is out of date
  • Package has warnings
  • Have out of date dependencies
  • Has dependencies with warnings
  • Has unit tests
  • Has 100% unit test coverage
  • All tests pass
  • Makes network calls
  • Writes to file system
  • Threat assessment
  • Package capabilities (what API’s are being used)

NuGet, Visual Studio Gallery, Visual Studio Marketplace

NuGet, Visual Studio Gallery, and Visual Studio Marketplace serve compiled code which is evaluated differently than JavaScript. Microsoft will need to determine the best way to evaluate and report on these packages.

Funding

This proposal affects developers and infrastructures from all over the world.

As a software engineer, I know that while there will be challenges, the problems identified in this proposal are solvable.

Getting big corporations and government to proactively and cooperatively, take on and complete a task because it’s the right thing to do is a challenge that must be initiated.

Waiting until there is a problem and then trying to stem the tide and roll back the damage is a poor strategy.  Benjamin Franklin said, “an ounce of prevention is worth a pound of cure,” he is correct.

I honestly do not believe getting funding for a project of this scope will be any problem.

Next Steps

Big players need to meet and solve this problem.

Developers, start the conversation in your sphere of influence and contact big players and let them know your concerns.  Request that they take proactive action now.

Close

Have a great day.

Just a grain of sand on the worlds beaches.

 

Angular 1.5.7 Components ES6 and jspm

Purpose

The purpose of the blog post and accompanying simple example project is to show you how to:

  • Create an ES6 Angular 1.5.7 super simple web application with navigation
  • Use Angular 1.5.7 Components
  • Use Angular Component Router  (not the constantly changing Angular 2 Router)
  • Bootstrap an ES6 Angular 1.5.7 application
  • Set up ES6 Angular 1.5.7 modules
  • Configure the Component Router
  • Provide a root component that hosts the entire application; providing a placeholder for the Component Router to navigate components into
  • Demonstrate writing super clean ES6 code that is 98% void of the word Angular.
  • Provides two Components that the app can navigate to.

This sounds like a lot, but it’s accomplish with only a few succinct ES6 files.

Background

I’m a total fan of Angular 1.x and now Angular 1.5.x after watching Scott Alan’s Pluralsight Course on Building Components with Angular 1.5.

I’m a fanatic about authoring my JavaScript using ES2015 (ES6, Harmony) and using jspm as my package manager.  This combination of language and package management is so clean and simple.

Scott’s course uses ES5.  Probably a good decision as it keeps the concept count down for Angular 1.x developers who still use ES5.

I highly recommend you watch the course; in about 90 minutes you’ll be another convert to using Angular 1.5.x Components.

I have looked at both Aurelia and Angular 2.  They are both still in beta and undergoing API and tooling changes. I’m very keen on Aurelia and am looking forward to adopting this product in the future.  What I like most about Aurelia is that the team embraced convention over configuration which dramatically reduces the boiler maker code for common scenarios.  Maybe Angular 2 will one day refactor their API to do the same.

Introduction

Authoring Angular 1.x or 1.5.x apps using ES6 with jspm is  simple and the code is very clean.  I have a project that demonstrates using Electron, Angular 1.x, ES6, and jspm. I will be creating a new project that uses Angular 1.5.7, Electron, ES6, and jspm very soon.

When using ES6 in today’s browsers or in Electron, the ES6 must be transpiled to ES5.  jspm hides all  that complexity and just does it for you. 

Gulp also has a module called gulp_jspm with an option, “selfExecutingBundle” that will essentially pre-compile, bundle, and minify all of your application’s ES6 to ES5.  Heck, it even removes all traces of ES6 libraries from the bundle.

Transpiling, bundling, and minification are part of “real world ES6 development.”  I just like that jspm makes this process simple and almost 100% transparent. 

Please note:  jspm is not the only game in town.  There are many other techniques, frameworks, build systems, etc., that accomplish the same task, producing the same end result.  When I did my study last year, I found that jspm worked best for me.  I recommend that you look at all the options and tools, read many blog posts on the subject just like I did. Then choose the one you understand and can be successful with.

Please note:  This application does not take any dependencies on the volatile and changing Angular 2 Beta.  The Component Router used in this project, is the original Angular 2 router and its works great.  I strongly recommend staying away from Angular 2 dependencies until the team has had time to ship RTM bits and ensure they have an approved, and good story for Angular 1.5.x integration.

Additionally, I have yet to see a compelling reason to write production code in Angular 2.  Like you, I have Angular 1.x projects in production and that run everyday and perform beautifully. 

Application Startup

Before you can run off and write the next awesome app using Angular 1.5.7 Components and ES6 we need to learn how the application starts up.  As you’ll see there are differences between the ES6 jspm code I’ll present and the current AngularJS 1.x ES5 apps you’re writing today.

index.html

  • Is loaded by the browser or Electron
  • Loads up system.js and config.js using script tags
  • The bootstrap.js module is imported.  The act of importing a module causes it to execute
  • Notice you don’t see any Angular framework markup as we will be manually bootstrapping Angular.

<!doctype html>

<html lang="en">
<
head>
<
meta charset="utf-8">
<
meta http-equiv="X-UA-Compatible" content="IE=edge">
<
meta name="viewport" content="width=device-width, initial-scale=1">

<title>Angular 1.5.7 Components ES6 jspm</title>
</
head>
<
body>
<
script src="src/jspm_packages/system.js"></script>
<
script src="src/config.js"></script>
<
script>
System.import('app/bootstrap').catch(console.error.bind(console));
</script>

<app-root></app-root>
</
body>
</
html>

bootstrap.js

  • framework dependencies are loaded
  • application ES6 modules are loaded
  • when the modules are all loaded and the document is ready, then bootstrap Angular
  • Notice how Angular is imported and provided a name, “AppModule”  I now have full access to my module and can access properties like, “name”
// load our framework modules
import angular from  'angular';
import 'ngcomponentrouter';

// load our application ES6 modules 
import AppModule from './app.module';
import './app-root.component';
import './About/app-about.component';
import './Home/app-home.component';

angular.element(document).ready(() => {
    // bootstrap angular now that all modules have been loaded
    angular.bootstrap(document, [AppModule.name], {strictDi: true});  
});

app.module.js

  • framework dependencies are imported so we can use them
  • Angular module named “app” is created and the Component Routers is injected as a dependency
  • Component Router root component is configured. Look back to index.html and you’ll see the app-root component in the markup
  • Export the Angular “app” module
import angular from  'angular';
import ngcomponentrouter from 'ngcomponentrouter';

let module = angular.module('app', [ngcomponentrouter]);

// must tell the Component Router which component to navigate components into
module.value('$routerRootComponent', 'appRoot');

export default module;

app-root-component.js

  • Import the above app.module default export, which is the angular.module(‘app’).  Consumers have clean code now.  Angular no longer appears in the code.
  • Register the ‘appRoot’ component with the AppModule and set its template.
  • Configure the root component router
  • Last line configures the default route
import AppModule from './app.module';

AppModule.component('appRoot', {
  templateUrl: '/src/app/app-root.component.html',
  $routeConfig: [
    { path: '/home', component: 'appHome', name: 'Home'},
    { path: '/about', component: 'appAbout', name: 'About'},
    { path: '/**', redirectTo: ['Home']}
  ]
});

app-root.component.html

  • This is my incredibly simple application root object.
  • It provides some navigation links for the Home and About components
  • The ng-outlet directive is where the Component Router will site components as they are navigated to.
<h1>Hello World</h1>

<p>
  <a href="#home">Home</a>
</p>
<p>
  <a href="#about">About</a>
</p>

<ng-outlet></ng-outlet>

app-home.Component.js

  • Import the app.module
  • Register the ‘appHome’ component with the AppModule and set its template.
  • See how clean this code is?
import AppModule from '../app.module';

AppModule.component('appHome', {
  templateUrl: '/src/app/Home/app-home.component.html'
  });

Download

Make sure you have node.js and jspm installed globally.

You can download or clone the simple repro here: https://github.com/Oceanware/ng157es6jspm

After downloading or cloning, navigate to the folder and open a command prompt (terminal window for OS X or Linux) and execute:

npm install

npm start

Your browser will open and display the application.

Close

You can start to see the simplicity of Angular 1.5.7 and ES6.  Clean JavaScript files, very easy to understand the intent of the code.  Fun programming!

Have fun and be productive with Angular 1.5.7 and ES6.

Hope this helps someone and have a great day.

Just a grain of sand on the worlds beaches.