published_blue_ribbon

Published!

Tech: Angular, Angular-Cli, Docker, nginx

Challenge: the challenge was making & releasing the app. Utilized by the American Association of Colleges of Osteopathic Medicine for studying empathy, I am happy to report no bugs or issues since the release approximately 1 year ago! The icing on the cake is a small acknowledgment in a published research paper. The pudding..

published

 

 

 

 

 

published_pomee

 

{{ng}} Fork & Deploy

Tech: Angular, Kinvey, AWS S3, NPM, Gulp, CLI, Git

Challenge: take an existing Angular 1.5 repo (with Kinvey Data Store, hosted by AWS S3), fork it, and deploy! Luckily, I forked this project approximately 10 months ago. Some of the work will just be a memory jog. The challenge here is connecting the fork to Kinvey & AWS, which was previously done by another developer.

Code:

First, we use git and create a branch (git checkout -B new_app_instance master)  for the new project instance. I used the term ‘fork’ above incorrectly. In order to simplify the maintenance of multiple live, hosted instances of this “To Do List” application, we branch off of master and deploy the various instances separately to unique AWS S3 buckets.

Once on the new branch, let’s add in environment files. Three in this instance: local, dev, prod. Here is the sample format env.local.js.example:

ng_fork_deploy_env_file_ex

The local file allows localhost to connect to whatever instance you’d like, without having to muddle with official dev or prod files.

 

For dynamic elements, we use env variables and conditionals in Angular to display the appropriate text/div per instance.

ENV Variable:

<span flex>{{$ctrl.$state.current.data.title}}</span>

Conditional:

<div ng-if="$ctrl.envConfig.env == 'appInstance2' || $ctrl.envConfig.env == 'appInstance3'">

 

Next, we setup the AWS S3 bucket. Pretty simple because we clone an existing instance. The key here is to turn on static hosting! The S3 bucket will look for Angular’s index.html file as the entry point and Angular will take over.

ng_fork_deploy_static_hosting

 

Ok, the env variables, Kinvey credentials, and AWS instance are in place. Let’s add an npm command to our package.json file for easier deployment (and for this specific app instance):

"deploy:prod": "gulp build --environment prod && pushd dist && aws s3 cp --recursive . s3://to-do-app --acl public-read && popd"

 

Ready to deploy from the cli… npm run deploy:prod … aaaannnndddd error!

ng_fork_deploy_aws_error

 

Looks like there is a region mismatch. I want to check with region I am trying to deploy to:

aws s3api get-bucket-location --bucket to-do-app

 

And the same error rolls in! Something is amiss… time for some googling… I think I have to upgrade my aws version:

aws --version

pip install awscli --upgrade --user

 

Ok, once the awscli is updated, I rerun my bucket location command and realize I am trying to deploy to the wrong branch. Location:

{ "LocationConstraint": "us-east-2" } (and I want to deploy to 1)

 

So, I need to VIM into the aws config file and make an update. Since I have never done this before, I wonder where the file is!

find '.aws'

 

Vi into the .aws file, make the region update, and deploooooooooooooyy!

 

Note: spinning the instance up took 2-3 hours, and this post attempts to hit the highlights for easier fork & deploy in the future. 

{{ng2}} Dynamically Updating CSS Width in Boostrap Progress Bar Template (pt. 2)

Tech: Angular2, CSS, Bootstrap

Challenge: Refactor time! See part 1 here… creating a survey app, and want to pass the User’s progress as a string from parent component to progress bar child component. Then use ng2/CSS inline styling to dynamically update the progress bar fill width.

Code:

We keep the initialization variables, but make a slight change. We want a dynamic number, and a string created from the updating number on page change/user clicking “next”.

private progressBarNum: number = 0;

private progressBarStr: string = this.progressBarNum + '%';

 
Each time the User navigates to the “next” page, we run a function to update the progress bar value, and corresponding string for CSS interpretation. The main difference here is instead of a manual increment, we dynamically calculate the progress based on the total pages (44):

private updateProgress() {

this.progressBarNum = ( this.currentPage / 44 ) * 100;

this.progressBarStr = this.progressBarNum + '%';

}

 
We pass the current page number and CSS string to the progress bar component:

progress_bar_refactored_pass_values

 

And use ng2 Input to bring into component:

progress_bar_refactored_input

 

And finally use the incoming variables with ng2 to set the CSS width and display the current page:

div class="progress-bar custom-progress-bar"

role="progressbar"

aria-valuemin="0"

aria-valuemax="100"

[style.width]=progressBarStr

>

{{currentPage}}/44

/div

 
The finished product:

progress_bar_refactored_final_product

 

progress_bar_refactored_final_product_2

 

progress_bar_refactored_final_product_3

.css { Custom Radio Buttons }

Tech: CSS, Bootstrap, Angular2

Challenge: in a ng2 & Bootstrap application, create custom CSS styled radio buttons.

Solution: Google this topic, and you’ll quickly find solutions… however, most assume the radio buttons elements (label, input) are html siblings. In Bootstrap forms, the radio button input is a child element of the label. Thus, most easily-found solutions do not apply!

Our solution is to create image classes for checked/unchecked radio buttons, and use the ease & power of ng2 to set which image the user sees when clicking. Let’s take a look.

Code:

The initial key piece is to hide the default radio button:

input[type="radio"] {

display: none;

}

 

Now, the html to setup the button illustration:

div class="notSelected"

div

[class.selected]="listObject.name === formObject.capturedUserInput">

/div

/div

 

Let’s go through this html. In a minute, we will look at the dynamic ng2 code that sets the clicked button. The ‘notSelected’ class is the outer, empty circle indicating a radio button to click. The inner div contains ng2 code for setting a CSS class, which will be a CSS illustration within the outer illustration. A circle within a circle.

css_custom_radio_css

 

And the result:

css_custom_radio_actual_btns

 

Lastly, the ng2 piece to tie it together.

[class.selected]="listObject.name === dbObject.capturedUserInput"

 

To create the radio button list, we iterate over a list of objects with a ‘name property’ to be displayed.

input type="radio"

name="radioListName"

[(ngModel)]="dbObject.capturedUserInput"

value="{{listObject.name}}"

>

When the user clicks on a radio button option, the ngModel connection adds the value to the dbObject. Then the DOM picks up the new dbObject value and assigns the inner class, thus displaying a circle within a circle!

 

Reference:

http://stackoverflow.com/questions/35269179/angular-2-conditional-class-with-ngclass

CSS circles – CSS3 concentric Circles

{{ng2}} Class/Service into Interface Export

Tech: Angular2, TypeScript

Challenge: refactor a service into an interface exported with accompanying array. Application is a single page survey. Future iterations may have different questions/answer options, so an early architecture decision was to break out different sections of the survey into components.

I modeled the structure after viewing tutorials and learning the power of ng2 at stackskills. Code was clean and application working smoothly. I submitted the code for review with a senior colleague, and the recommendation was to streamline the service.  Basically, a class with service is only needed when behavior is attached to the model, such as initializing in the constructor. I created the class & service to separate the creation of question/answer components from the main survey component. Let’s take a look at the initial code, and then the refactored solution.

 

Initial Code:

For this example, we will look at the ‘Speciality’ question of the survey. The survey has many components, and this refactor was mirrored throughout the code. Two files for Speciality in a directory of the same name.

Model:

ng2_interface_export_specialty_model

Service:

ng2_interface_export_specialty_service

 

Make the service available in the app.module.ts:

import { SpecialtyService } from './specialty/specialty.service';

providers: [ SpecialtyService ]

 

And available in the main survey.component.ts:

import { Specialty } from './specialty/specialty.model'

import { SpecialtyService } from './specialty/specialty.service'

 

Setup for the constructor in survey.component:

private _specialtyService:SpecialtyService;

private _specialties:Array = [];

 

And the survey.component constructor:

constructor(

specialtyService:SpecialtyService

{

this._specialtyService = specialtyService;

this._specialties = this._specialtyService.getSpecialties();

}

 

Whew! Lots of code.

 

Refactored Solution:

Let’s look at the new Specialty file, now the only file in the Specialty directory!

ng2_interface_export_refactored_specialty

 

No import is needed now in the app.module. We still need to import in survey.component:

import { Specialty, specialtiesArray } from './specialty/specialty'

 

And the streamlined setup and array population:

private specialties:Specialty[] = [];

constructor() {

this.specialties = specialtiesArray;

}

 

Takeaway: refactor is significantly less code, easier to understand, and more appropriate ng2 architecture.

{{ng2}} SSL-Certified Application in Docker

Tech: Angular2, Lite-Server, BrowserSync, Docker

Challenge: launch SSL-certified ng2 development instance on Docker

Code:

Two steps…

  1. Configure ng2 bs-config.json file. We create a folder in the js files deploy directory, https_certs. The key & cert values will be mapped in step 2:

ng2_ssl_bs_config

 

2. Map the certification files on the docker server to the ng2 app when launching the app. cli:

docker run --name containername -td -p 6001:6001 -v /var/docker/certs:/deploy/https_certs imagename

 

Reference:

my own post regarding this process with Ruby on Rails!

BrowerSync Options

{{ng2}} Application Not Loading in Safari

Tech: Angular2

Challenge: local development application is working & displaying properly in Firefox and Chrome. Not so in Safari!

Error:

Error: (SystemJS) Unexpected identifier 'resolvedUrl'

 

Current code in systemjs-angular-loader.js:

let resolvedUrl = url;

 

Corrected:

var resolvedUrl = url;

 

Takeaway: More research/troubleshooting needed in this application for browsers and es5, es6 compatibility. A better solution might be to configure an es6 compiler to run in Safari.
 
Reference:

https://github.com/angular/quickstart/issues/437

{{ng2}} Dynamically Updating CSS Width in Boostrap Progress Bar Template (pt. 1)

Tech: Angular2, CSS, Bootstrap

Challenge: creating a survey app, and want to pass the User’s progress as a string from parent component to progress bar child component. Then use ng2/CSS inline styling to dynamically update the progress bar fill width.

Code:

First, setup the parent SurveyComponent values:

private progressValueNum:number = 10;

private progressValueStr:string = "10%";

 

In the child ProgressBarComponent, we connect the parent-child variable relationship:

import { Input } from '@angular/core';

@Input() progressValueStr:string;

 

And finish wiring the connection in survey.component.html:

progressbar [progressValueStr]="progressValueStr"> /progressbar

Note: the [leftSideValue] is the child ProgressBarComponent, or the receiver of the input. The “rightSideValue” is the parent component variable.

 

Second, let’s look at the progress_bar.component.html for the ng2 dynamic styling. In the Bootstrap progress-bar div:

[style.width]=progressValueStr

 

Lastly, we update the progress bar value string when the User clicks “next”:

private userClickedNext() {

this.progressValueNum = this.progressValueNum + 10;

this.progressValueStr = this.progressValueNum + "%";

}

The string is updated and automatically passed to the child component.

Note: the string update is rudimentary at this point. It needs refactoring for User “back” behavior (subtracting 10% instead of adding 10%). Additionally, the number of pages / percentage progression is unknown at time of this post. Backlog items entered for both, as well as creating the initial percentage based on number of pages in survey (currently a hard-coded 10/10%) … refactoring ahead ==> read part 2!

 

Reference:

http://stackoverflow.com/questions/33328347/angular2-dynamic-change-css-property