Nativescript: Binding ActivityIndicator to image load

Created on 24 May 2017  路  4Comments  路  Source: NativeScript/NativeScript

Hi,
I'm using Angular and the specific behavior is hapenning inside a Modal screen.
I want to display an activity indicator while image is loading following the example code on the website. However, it does not show.
Here is the code, appreciate your feedback:
<Image #productImg id="productImg" [src]="product.itemImageSize3Url" horizontalAlignment="center" class="product-image"></Image>

 @ViewChild("productImg") myImageRef: ElementRef;
ngAfterViewInit(){
        let indicator = new activityIndicatorModule.ActivityIndicator();
        var image = this.myImageRef.nativeElement; //view.getViewById(this.page, "productImg"); - this did not work as well
        indicator.width = 40;
        indicator.height = 40;
        indicator.className="activity-indicator";
        indicator.bind({
            sourceProperty: "isLoading",
            targetProperty: "busy"
        }, image);
    }
question

Most helpful comment

Hi @tigrenok00,
Creating UI component via code behind is not recommended in NativeScript Angular 2 project.
For this case, you could use GridLayout and display the ActivityIndicator and the Image on the same row and column.
In this scenario, the Indicator will be shown, until the image is loading.
For example:
HTML

<StackLayout class="page">
    <GridLayout rows="auto" columns="*">
        <ActivityIndicator row="0" col="0" #activityIndicator busy="true" class="activity-indicator"></ActivityIndicator>
        <Image row="0" col="0" #productImg id="productImg" [src]="itemImageSize3Url" horizontalAlignment="center" class="product-image"></Image>
    </GridLayout>
</StackLayout>

TypeScript

import { Component, OnInit, ViewChild, ElementRef } from "@angular/core";
import {ActivityIndicator} from "tns-core-modules/ui/activity-indicator"
import { Item } from "./item";
import { ItemService } from "./item.service";

@Component({
    selector: "ns-items",
    moduleId: module.id,
    templateUrl: "./items.component.html",
})
export class ItemsComponent implements OnInit {
    items: Item[];
    itemImageSize3Url="";

    constructor(private itemService: ItemService) { }

    ngOnInit(): void {
        this.items = this.itemService.getItems();
    }

    ngAfterViewInit(){
    setTimeout(()=>{
        this.itemImageSize3Url = "https://www.w3schools.com/css/trolltunga.jpg";
    }, 2000);

    }
}

If you still have some problems, please send me sample project, which could be debugged locally.

All 4 comments

Hi @tigrenok00,
Creating UI component via code behind is not recommended in NativeScript Angular 2 project.
For this case, you could use GridLayout and display the ActivityIndicator and the Image on the same row and column.
In this scenario, the Indicator will be shown, until the image is loading.
For example:
HTML

<StackLayout class="page">
    <GridLayout rows="auto" columns="*">
        <ActivityIndicator row="0" col="0" #activityIndicator busy="true" class="activity-indicator"></ActivityIndicator>
        <Image row="0" col="0" #productImg id="productImg" [src]="itemImageSize3Url" horizontalAlignment="center" class="product-image"></Image>
    </GridLayout>
</StackLayout>

TypeScript

import { Component, OnInit, ViewChild, ElementRef } from "@angular/core";
import {ActivityIndicator} from "tns-core-modules/ui/activity-indicator"
import { Item } from "./item";
import { ItemService } from "./item.service";

@Component({
    selector: "ns-items",
    moduleId: module.id,
    templateUrl: "./items.component.html",
})
export class ItemsComponent implements OnInit {
    items: Item[];
    itemImageSize3Url="";

    constructor(private itemService: ItemService) { }

    ngOnInit(): void {
        this.items = this.itemService.getItems();
    }

    ngAfterViewInit(){
    setTimeout(()=>{
        this.itemImageSize3Url = "https://www.w3schools.com/css/trolltunga.jpg";
    }, 2000);

    }
}

If you still have some problems, please send me sample project, which could be debugged locally.

This is perfect, and so simple, thank you!

@tsonevn Very useful. I did another little thing. When the image is loaded, remove the Activity Indicator. I don't know for sure if this is a little more optimized. With the new release of {N} 3.1 we can prove it, using the inspect element on chrome to view the 'html' to be sure if the *ngif still there behind the image.

My code was.

<GridLayout class="item" >
    <ActivityIndicator busy="true" *ngIf="image.isLoaded"> </ActivityIndicator>
    <Image #image src="http://i.imgur.com/JAvJKTU.png" stretch="aspectFill"></Image>
</GridLayout>

@Component({
    selector: 'card',
    moduleId: module.id,
    templateUrl: './card.component.html',
})
export class CardComponent implements {

    @ViewChild('image') image: Image;

    constructor() { }
}

The property isLoaded of the image has very bad performance, a lot of delay. We need to put the image after the activity indicator if don't you will see a unexpected behavior.

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Was this page helpful?
0 / 5 - 0 ratings