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.

Friday, August 11, 2017

NativeScript and that "status 200 url null" error

This error confused me while developing with NativeScript trying to do a rest api call. Without digging thru the error object, you only get: "Response with status: 200  for URL: null" for the error text. Not exactly useful.

I then had to run "tns debug android" and dig thru the error object by doing adding a "json()" method call to it. I then got a more verbose error message. Something like:

"Error: java.net.ConnectException: failed to connect to localhost/127.0.0.1 (port 8000): connect failed: ECONNREFUSED (Connection refused)"

The chrome devtools also was cryptic only saying that the rest api call "Stalled".

Ok. So I then visited StackOverflow looking for a solution. No dice. Until, I realized that I'm doing development using an android emulator which is basically a virtual machine. And being a virtual machine calling 'localhost' or 127.0.0.1 is calling itself. The address is loopback address of the vm NOT my machine. No wonder the rest api call was failing. Fortunately, the android emulator networking is setup to work with localhost development.

The solution is to just change the rest api call from 'http://localhost/api' to http://10.0.2.2/api'.

Now it works.

For the curious, my rest api server is a Django Rest Framework app running locally.