Google analytics code

Tuesday, July 11, 2017

Angular: Getting started with ngUpgrade

I've started work on upgrading an old AngularJS project to Angular using ngUpgrade. I read about this awhile ago (Angular 2 RC 2) but haven't worked with it. There's a lot of outdated information that made it hard to get anything done. I'll show you what worked for me.

The first step is placing your AngularJS application in a Angular shell. The easy way to do this is use Angular CLI to create a new project ("ng new angular_project_name") and copy your files in as static resources. One of the files created by the CLI is called .angular-cli.json. Use the apps.assets to specify single or folders images, apps.styles for css files and apps.scripts for any single javascript files. The only way to copy whole folders of files is to specify them in apps.assets. It's probably not the best way but this whole process is so you can move away from the old project structure. Hopefully you had a good build process so there are only one or two minified files you need to copy.

Now we need to make sure @angular/upgrade is part of your Angular project. Check package.json and look in the dependencies object. If you don't see @angular/upgrade then we'll need to add it via npm. Use the command "npm install -g @angular/upgrade --save" in the root of your Angular project. Once the install is done it should show in the package.json file.

The next step is changing the bootstrap process for AngularJS. Angular will now be in charge of starting the AngularJS app. My project relied on the ng-app tag on the body element. This needs to be removed. If you app uses strict-di this also needs to be removed. Open app.module.ts and add a new method to the AppModule class called ngDoBootstrap. In this method we'll use a variable that will assist us in 99% of the conversion process.

Add "import { UpgradeAdapter } from @angular/upgrade;" at the bottom of your imports section. Also we need to import forwardRef from @angular/core. This should be on the second line of your file. It should now look like this "import { NgModule, forwardRef } from '@angular/core';". Before @NgModule add this line "export const upgradeAdapter = new UpgradeAdapter(forwardRef(() => AppModule));". This variable contains methods that will allow us to upgrade AngularJS components and services so they can be used in Angular components. We can also downgrade Angular components and services so they can be used in AngularJS code.

In ngDoBootstrap add this line. "upgradeAdapter.bootstrap(document.body, NAME_OF_YOUR_APP, {'strictDi': true});". This will allow Angular to bootstrap your AngularJS application. In the root of your application use the command ng serve to start the dev environment server. Your app should be up and running.

The next steps are using upgradeAdapter.downgradeNg2Component, downgradeNg2Provider, upgradeNg1Component, upgradeNg2Provider to start converting your codebase. Here's a link to the official documentation on converting your app. Here's a link to the official documentation on UpgradeAdapter. Here's a link to my AngularJS project and here's a link to the hybrid project. Hope this helps you out.




Friday, October 2, 2015

Ionic Framework / UI Router: Remove a query parameter from the URI

I've been working with Ionic Framework for most of the year and finally launched the alpha version of my project. I've enjoyed working with it, but like everything you'll run into something that makes you bang your head on the desk for a few days. The most recent case of this was trying to remove a parameter from the URI.

If a user needs to reset their password I send them a URI that looks something like this.
http://this.that/login?resetKey=1234

After the user finishes the steps to reset I want to clean up the URI so if they hit the refresh button it doesn't trigger the reset process again.
http://this.that/login

I had the worse time finding an answer on google. After a few days of digging through UI Router documentation I finally found a combination that worked.

First you need to inject the $state param into your controller. We'll use the go method and redirect to the current URI using the current router name. The current route name can be accessed through the $state.current.name property. Next we need to specify the parameter we want to remove from the URI. We'll use an object with the key as the param name and the value will be null. Lastly we don't want to trigger the route again so we'll set the notify property to false.

The final command looks like this.
$state.go($state.current.name,{'resetKey': null},{'notify': false});

Such a simple command. So much digging. UGH!

Tuesday, June 23, 2015

HTML / CSS 3: Progress bar example

I've been working with the progress element and trying to get it to look nice across different browsers. It doesn't help that most of the styling elements are pseudo elements.

Here's the MDN page on the progress element.

The big issue I ran into was trying to style the element for Chrome and Firefox.
Chrome uses the following styles to change the look of the element:

progress::-webkit-progress-bar
This will style the background of the progress bar.

progress::-webkit-progress-value
This will style the growing value inside of the progress bar.

Firefox uses the following value:
progress::-moz-progress-value
This will only let you style the growing value inside of the progress bar. You can't style the background.

The other catch is you can't combine the values in your css. For example this won't work

progress::-moz-progress-value,
progress::-webkit-progress-value{

}

None of your styles will take and the bar will fall back to it's unstyled default.

Here's the html I was playing with.
Here's a link to a jsFiddle of the following code


/* http://www.hongkiat.com/blog/html5-progress-bar/ */
.progress-bar{
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
}

/* Can't share styles. Chome gets angry */
/* FF style the progress bar */
.progress-bar::-moz-progress-value{
    background: #3399ff;
    border-radius: 12px;
    box-shadow: 0 2px 5px rgba(0, 0, 0, 0.25) inset;
}

/* Chrome style the background of the progress bar */
.progress-bar::-webkit-progress-bar{
    background: silver;
    border-radius: 12px;
}

/* Chrome style the progress value */
.progress-bar::-webkit-progress-value{
    background: #3399ff;
    border-radius: 12px;
    box-shadow: 0 2px 5px rgba(0, 0, 0, 0.25) inset;
}

Wednesday, September 17, 2014

Sencha Touch: Android Halo Light Theme

One of the things I love about Sencha Touch is the built in themes. Android has 4.x has two themes: Halo Dark, Halo Light.  There is only one Android theme for Sencha Touch and it's dark. I've been bugging them for awhile to include a light theme and their response was "You do it".

I googled for a long time and couldn't find a theme someone else did. I gave in and decided to make my own theme after finding this one. It's beautiful. I read his breakdown and he created a theme by copying the winPho theme and made changes until he was happy. I did something similar. I copied the Android theme and started digging in.

That's when I found it. There is a Sass variable in /[Sencha SDK folder]/resources/themes/stylesheets/sencha-touch/mountainview/var/_Class.scss called $dark-theme. If you set this variable to false in your local sass file for android it becomes a light theme.

I wish this was explained better. It's only through source code diving can we find the true answers.

Zend Framework 2: Using mysql functions in SQL classes

The built in ZF2 classes for sql queries have been wonderful to use. I like that it takes care of escaping data and saves you from messy string all over your codebase. I ran into a problem when trying to do something "complex".

Here is an example of the SQL I was trying to write.
INSERT into `table` SET `col1` = FROM_UNIXTIME(?)

When I tried running this the mysql method was quoted
`FROM_UNIXTIME(?)`
I started digging around and found an extra class required if you want to use functions in the escaped data spot. It's called an expression. Here is how they're used in the insert class.

$insert->into($tableName)
       ->values([`col` => new \Zend\Db\Sql\Expression("FROM_UNIXTIME(?)","?", [\Zend\Db\Sql\Expression::TYPE_VALUE])]);

Now the function won't be quoted and the value can be safely escaped when execute is run.


Here's some documentation on how expressions are used in a where clause.

Monday, July 28, 2014

Angular: Form element not attaching to $scope

I'm well into a redesign using AngularJS as my front-end framework. After a small learning period I'm in love. It's a fantastic way to tie your UI to your backend. That said there is still some work to be done.

I'm breaking my project into modules that are included with the ng-include tag. This helps shrink the code on the page into manageable chunks. It nice when you're using a very verbose framework like Bootstrap.

All of my forms are wired up using Angular's form validation. Once again this is fantastic. Being able to watch the inputs in real time and display helpful errors is great. I ran into an issue trying to reuse a form after I've removed it from the users view.

<form name="createUser">
    <input name="name" ng-model="formObj.name" />
    <input name="email" ng-model="formObj.email" />
</form>

I should be able to access the form in my angular in this fashion.

// This will reset any validation errors on the form
$scope.createUser.$setPristine();

This wasn't working for me and I spent a lot of time trying to figure out why. Here is how my code looked.

<div ng-controller=“controllerName”>
    <div ng-include=“ ‘path-to-the-template’ ”></div>
</div>

<!—- Inside path-to-the-template -—>
<form name="createUser">
    <input name="name" ng-model="formObj.name" />
    <input name="email" ng-model="formObj.email" />
</form>

One thing to consider is when Angular is starting up the controller code the form isn't attached yet. When you click the button that submits the form it will be attached by that time. I was still unable to access the form element.

Update

I submitted this as a bug to the git repo and got a response very quickly. That team is really on top of things. Turns out when you use ng-include it creates a new scope var. This is how the setup should look.

<!—- The vars should live in the controller. I placed them here for the example. -—>
<div ng-controller=“controllerName” ng-init="form={}; model={}" >
    <div ng-include=“ ‘path-to-the-template’ ”></div>
</div>

<!—- Inside path-to-the-template -—>
<form name="form.createUser">
    <input name="name" ng-model="model.name" />
    <input name="email" ng-model="model.email" />
</form>

Now the include can reference the variables from the parent scope. The form and it's input should now be accessible.

Friday, June 27, 2014

Zend Framework 2.x Learn ZF2 by Example: Protecting our Pages - Authentication type

I'm starting to implement authentication on my web app and I ran into a problem with the example in the book.

The example on page 146 uses MD5 as a encryption scheme.

$adapter = new DbAdapter($db,
                         'users',
                         'login',
                         'password',
                         'MD5(password)');

The adapter builds a simple SQL query that will check the table, match the user name and password then let you know if it's valid. The problem lies in the 5th parameter. When I tried to match an account I know works it kept saying the account wasn't valid. After digging into the documentation I found the 5th parameter wasn't configured right. It should be 'MD5(?)'.

$adapter = new DbAdapter($db,
                         'users',
                         'login',
                         'password',
                         'MD5(?)');

After the change the auth adapter works perfectly. Hope this helps save you some time.