Friday, October 23, 2015

Alignment problem of Firefox that's non-existent on Chrome

Given this html:

<span class="form-search"></span>
<input class="search-query form-control" style="width: 200px" placeholder="Live search"/>


And CSS:

span.form-search {
    position: relative;       
}
span.form-search:before {
    display: block;
    width: 14px;
    height: 14px;
    content: "\e003";
    font-family: 'Glyphicons Halflings';
    background-position: -48px 0;
    position: absolute;
    top:8px;
    left:8px;
    opacity: .5;
    z-index: 1000;
}
input.search-query {
    padding-left:26px;
}

Live code: https://jsfiddle.net/L1pb9km3/

The above display perfectly ok with Chrome, but not on Firefox.

Chrome:





Firefox:






The work-around to make it work on Firefox is simple, just add a float: left to the span.form-search

span.form-search {
    position: relative;   
    float: left;    
}

Live code: https://jsfiddle.net/axjk3xss/

Yes it's easy to land on comet than to properly align stuff on web using CSS.

Tuesday, October 20, 2015

Can't set the $pristine on constructor

Let's say you are using a directive that has problem with pristine, i.e., on first load the aForm is already dirty:

<form name="c.aForm">
<someDirectiveWithBugHere></someDirectiveWithBugHere>
</form>

<div>{{c.aForm.$pristine}}</div>




You can't set the aForm to pristine on constructor, as aForm is not yet defined while on constructor:
module App.UserEdit
{
    export class MainController
    {
        aForm: ng.IFormController;

        constructor(public Resources: InhouseLib.Resources)
        {
             this.aForm.$setPristine();

        }
    }
}

Setting the form to pristine while on constructor would give this result:
TypeError: Cannot read property '$setPristine' of undefined
    at new MainController

A work-around is to set the pristine state after the form is loaded, and by calling the expression (that will set the pristine to clean) on ng-init:
<form name="c.aForm">
<someDirectiveWithBugHere></someDirectiveWithBugHere>
</form>
<div ng-init="c.setClean()"></div>

<div>{{c.aForm.$pristine}}</div>

Remove the $setPristine from the controller and move it to setClean:
module App.UserEdit
{
    export class MainController
    {

        aForm: ng.IFormController;

        constructor(public Resources: InhouseLib.Resources)
        {
        }
    
        setClean(): void
        {
            this.aForm.$setPristine();
        }
    }
}


Or if you don't want the controller to have concerns on those stuff, you can initialize the form's state directly on html.

<div ng-init="c.aForm.$setPristine();"></div>

<div>{{c.aForm.$pristine}}</div>

Sunday, October 4, 2015

Prevent ui.router's ui-sref from reloading the page

If a ui-router link points the page where it resides, it will cause a page reload on the page(s) that are reloaded, and thus it will cause flickering or noticeable delay.

<a ui-sref="root.app.editAd({id: ad.itemId})">{{ad.title}}</a>

To improve that, just perform ajax on an ng-click and just fetch the data that are needed to populate the information on the page, and prevent the href from reloading the page by using $event.preventDefault(). The href will just be used for bookmark purposes or if the user want to open the link on another tab or window. We can use ui.router href method for translating the state to link.

<a 
ng-click="ctrl.AppWide.edit(a.itemId); $event.preventDefault()" 
title="Change Information" 
href="{{c.$state.href('root.app.editAd',{id: a.itemId})}}" 
 {{a.title}}
</a>


To change the url after performing an ajax operation, use $state.go and pass the parameter notify false to it, so it will just change the url and not do a partial page reload.

this.$state.go('root.app.editAd', {id: this.savedId}, {notify: false});


Note: As of the time of the time of this writing, the notify false has a bug, it invokes the originating controller twice and sometimes it rejects the link the user clicked on from going to the link's page. There's already a solution to that, but it's not yet on the latest release of angular ui.router, have to patch the ui.router manually.


Happy Coding!