Monday, October 16, 2017

Doing listviews with empty lists and pullrefresh in Nativescript-ng

This was a pain in the butt to do right and I had to do a "bit" of trial and error to get this right.

All I wanted do was show a "centered" bold, large text on the screen when a list is empty and the actual list view when there's data on the list with both having support for pull to refresh action.

Googling this well probably lead you to Telerik's doc on the RadListView for pullToRefresh which I call shenanigans on because I couldn't make it to work. So we move to next idea which is Brad Martin's pullToRefresh nativescript plugin.

I did get Martin's nativescript plugin to work on my first attempt sans a bug that was a bit odd. I'm not even sure if the bug can be replicated on another machine. Anyhow, my first attempt's code looked like this:

 <PullToRefresh (refresh)="refreshList($event)" row="1">  
     <GridLayout horizontalAlignment="center" verticalAlignment="center"   
           rows="*" columns="*" *ngIf="emptyList()">  
       <Label horizontalAlignment="center" verticalAlignment="center" row="1" column="1" class="h2"   
           text="No Orders Available."></Label>  
     </GridLayout>   
     <ListView [items]="ordersList"   
          (itemTap)="onOrderTap($event)" class="list-group">  
       <ng-template let-order="item" let-odd="odd" let-even="even">  
         <GridLayout [class.odd]="odd" [class.even]="even" columns="auto, *" rows="auto">  
           <Label col="0" class="iconbkg" text=""></Label>  
           <avatar [avatardata]="order.avatar_prop"></avatar>  
           <StackLayout col="1" class="formMessage">  
             <GridLayout columns="auto, 100, *" rows="auto">  
               <Label class="h3 text-left" col="0" [text]="'Order #' + order.number"></Label>  
               <Label class="h3 text-right" col="1" [text]="order.date_placed | date:'MMMM dd yyyy'"></Label>  
             </GridLayout>                            
             <Label class="body" [text]="'City: ' + order.shipping_address.line4 + ', ' + order.shipping_address.state"></Label>  
             <Label class="body" [text]="order.lines.length + ' Item(s)'"></Label>  
           </StackLayout>  
         </GridLayout>  
       </ng-template>  
     </ListView>  
   </PullToRefresh>  


If you refer to the inner Gridlayout with the *ngIf element. The idea was to show this gridLayout when the list is empty. Don't bother with the ListView component because it will not show anything if [items] is empty.

The problem was when I do a pull to refresh, it was causing a crash in the android emulator saying that it was referencing a null view of some sort.

I eventually got it to do want I wanted. I did two things:

1. Move the empty list gridLayout into its own pullToRefresh container. Like so:

<PullToRefresh (refresh)="refreshList($event)" row="1" col="1" *ngIf="emptyList()">  
     <GridLayout horizontalAlignment="center" verticalAlignment="center" rows="*" columns="*">  
       <Label horizontalAlignment="center" verticalAlignment="center" row="1" column="1" class="h2"   
           text="No Orders Available."></Label>  
     </GridLayout>      
   </PullToRefresh>  

   <PullToRefresh (refresh)="refreshList($event)" row="1">  
     <ListView [items]="ordersList"   
          (itemTap)="onOrderTap($event)" class="list-group">
.....


2. I removed the ChangeDetectionStrategy in the @component declaration of the view class.

 With these two changes, the error no longer happened and it works perfectly.

Thursday, September 14, 2017

VS Code with code ligatures

Code ligatures are these cool things I just found out about recently that replace text to symbols. For example: '!=' turns into '!='. That pretty cool.

Now, if you're not seeing the equal symbol with a slash across it, that just means you haven't installed correct font for code ligatures - FiraCode. Click here for install instructions.

With the font installed, time to activate this for VS Code, you'll have to modify your settings.json - either your users or your workspaces settings.json.

FYI, most editors and IDEs are supported except for a few; most notable are Eclipse and Sublime which are not supported yet. Huh....

To open settings.json, from the File menu choose Prefereneces, Settings or use the keyboard shortcut Ctrl +,. Add these lines and restart VS Code.

    "editor.fontFamily": "Fira Code",
    "editor.fontSize": 14,
    "editor.fontLigatures": true

You might have to wrap the "Fira Code" font with extra apostrophes like
"'Fira Code'".
if it doesn't work.

Read up more about code ligatures.

Wednesday, August 30, 2017

Quick Letter Avatars for List in NativeScript

Letter Avatars are these elements often associated with Gmail - especially on it's Android client. So, being a programmer lacking in design skills, I decided to copy them for a Nativescript app I'm working on that had lists.

My approach to this was just to use a Label element and CSS. It's hacky but it works and in my world if it works it's not stupid.

So, we start on the component template:

 <GridLayout rows="*">  
  <ListView [items]="ordersList" (itemTap)="onOrderTap($event)" class="list-group">  
   <ng-template let-order="item" let-odd="odd" let-even="even">  
     <GridLayout [class.odd]="odd" [class.even]="even" columns="auto, *, auto">  
       <Label class="lavatar" text="VP" style="background-color: goldenrod; color: white;"></Label>  
       <StackLayout col="1" class="item-text">  
         <Label [text]="'#' + order.number"></Label>  
         <Label [text]="'Order by ' + order.guest_email"></Label>  
         <Label [text]="order.date_placed | date:'MMMM dd yyyy'"></Label>  
       </StackLayout>  
     </GridLayout>  
   </ng-template>  
  </ListView>  
 </GridLayout>   

The important thing here is the Label with the class "lavatar" which as the following rules:

.lavatar{
    text-align: center;
    font-size: 20;
    font-weight: bold;
    padding: 18;
    border-radius: 40;
    border-color: salmon;
    border-width: 0.5;
    width: 64px;
    height: 64px;
}

The border-radius is what's actually rounds the element.

Unfortunately this rule only works on "known" dimensions - width and height. For a more dynamic solution, I think you'll have to keep looking.

Settings the colors is based on the fact that CSS rules have the "cascade rule" so the final style rule applied is what's on the element. That's why the Label has a style attribute despite knowing it's in bad taste.

 Oh well.