Creating a dynamic horizontal list of buttons in NativeScript

I am currently diving into the world of NativeScript and I find myself struggling a bit with the MVVM concept, specifically when it comes to binding. I have configured my environment to work with TypeScript.

On my HomePage, I am tasked with creating a horizontal list of buttons. However, before I can do that, I need to fetch the necessary button data from the server:

let page: Page;
let viewModel = new MainViewModel();
let fetchCategoriesUseCase: FetchCategoriesUseCase = new FetchCategoriesUseCase(new InMemoryCategoriesRepository());

export function navigatingTo(args: EventData) {
    page = <Page>args.object;    
    page.bindingContext = viewModel;
}

export function onMapReady() {
    console.log("Map is ready"); 
    fetchCategoriesUseCase.handle(null).then((result: IFetchCategoriesResult) => {
        viewModel.categories = result.getCategories();
    });
}

and MainViewModel.ts

export class MainViewModel extends Observable {
    private mMap: Observable;
    private mCategories: Category[];

    public constructor() {
        super();    

        this.mMap = fromObject({
            latitude: 42.442574,
            longitude: 19.268646,
            zoom: 13
        });
    }

    get map(): Observable {
        return this.mMap;
    }

    get categories(): Category[] {
        return this.mCategories;
    }

    set categories(categories: Category[]) {
        this.mCategories = categories;
    }
}

In the main.xml, I have the following setup:

<AbsoluteLayout>
    <maps:mapView 
        left="0"
        top="0"
        width="100%"
        height="100%"
        latitude="{{ map.latitude }}" 
        longitude="{{ map.longitude }}" 
        zoom="{{ map.zoom }}"  
        mapReady="onMapReady"
        cameraChanged="onMapCameraChanged"/>

    <ScrollView
        left="0" 
        top="0"
        width="100%"
        orientation="horizontal">

        <Repeater items="{{ categories }}">
            <Repeater.itemsLayout>
                <StackLayout orientation="horizontal" />
            </Repeater.itemsLayout>
            <Repeater.itemTemplate>
                <Button text="{{ getName() }}"/>
            </Repeater.itemTemplate>
        </Repeater>
    </ScrollView>
</AbsoluteLayout> 

As I observed, upon starting my application, the list is initially empty (which is expected), but even after fetching buttons in the onMapReady() function and updating viewModel.categories, the list remains empty.

However, if I make changes to the XML file and save it, the NativeScript CLI will sync the changes to the device without recreating the entire page. This results in the buttons being displayed because the reference to the MainViewModel object was not lost and it contains the button data in the categories field. It seems like the issue lies in how I bind the data...

How can I resolve this problem? I believe it might be related to using ObservableArray, but I'm unsure of the correct implementation?

Answer №1

assign categoriesList(categories: Category[]) {
    this.categoriesData = categories;
    this.emitChange('categories', categories)
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Transferring the date from an HTML input to a TypeScript file in Angular when the button

On my HTML page, I have two input fields for dates that need to be passed to the backend along with other parameters when a button is clicked. Here is the current setup: <input [owlDateTime]="dt1" placeholder="From a date" [value]="dateFrom.value"& ...

Vue - Troubleshooting why components are not re-rendering after data updates with a method

Check out this simple vue component I created: <template> <div class="incrementor"> <p v-text="counter"></p> <button v-on:click="increment()">Increment</button> </div> </template> <script lan ...

What is the method for extracting search parameters as an object from a URL that includes a hash symbol?

Currently, I am dealing with a URL structured in the following format: https://my-app.com/my-route/someOtherRoute#register?param1="122"&param2="333" While I am familiar with fetching query strings from a standard URL, I am struggli ...

Is there a way to modify an image that has been dynamically inserted in an Angular application?

I'm facing an issue with dynamically added input files in Angular. Whenever I upload a file, it changes all the images of the input files instead of just the one I want to target. How can I resolve this problem? Please help. images = [ {url: &ap ...

Unveiling a plethora of utility functions by integrating them into services

In my Angular 7 multi-module application, I have a utility namespace structured as follows: export namespace Utils { export function util1 (arg: type) { } export function util2 (arg: type) { } ... } Some of these functions are used in templ ...

Mapping nested array of references in Angular Firestore

I am working with a collection called A, which contains documents that reference other documents in collection B. https://i.sstatic.net/C1HtT.png When fetching my A documents from the service, I receive an array of objects that are not usable. However, I ...

Resolving Modules: Using NPM to Install the Typescript Package Directly from Github

Recently, I decided to branch out and customize an existing npm package built in TypeScript to cater specifically to my unique requirements. I discovered that I could also install packages from GitHub branches using npm without any issues. However, after ...

Create a Typescript type extension specifically designed for objects with nested arrays of objects

After stumbling upon this inquiry, I am eager to adjust my code in a similar fashion, utilizing typescript and a more intricate object. Consider the type below: export type ImportationType = { commercialImportation: boolean dateToManufacturer: string ...

Issues with updating table data when clicking the "Remove Selected" button a second time in Angular 8

Whenever I click the "Remove Selected" button on my table, the selected rows with checkboxes should be deleted. The issue is that it works perfectly fine the first time I click the button, but if I repeat the same steps (click the checkboxes and then click ...

How can I test for equality with an array item using v-if in Vue.js?

Currently, I am facing a challenge in my Vue.js project where I need to determine if a number is equal to an element within an array. Here is the code snippet that I am working with: <div v-if="someValue != arrayElement"> // </div> I am st ...

Angular Custom Pipe - Grouping by Substrings of Strings

In my Angular project, I developed a custom pipe that allows for grouping an array of objects based on a specific property: import { Pipe, PipeTransform } from '@angular/core'; @Pipe({name: 'groupBy'}) export class GroupByPipe impleme ...

Guide to integrating Mongoose typings with Angular 2 webpack starter

As a newcomer, I'm hoping this issue is straight forward. I am currently utilizing the angular2-webpack-starter found on GitHub. Based on the mongoose documentation, it appears that including their JavaScript file allows for accessing a global varia ...

What is the best way to incorporate ControlContainer in an Angular component's unit test?

Is there a way to include ControlContainer in an Angular unit test? The error message I am encountering reads: NullInjectorError: StaticInjectorError(DynamicTestModule)[ChildFormComponent -> ControlContainer]: StaticInjectorError(Platform: core) ...

What purpose does a cast serve when used on a return type that is defined generically?

Consider this straightforward property access function export function accessProperty<T, K extends keyof T, P extends T[K]>(name: K, v: T): P { return v[name] as P } What is the significance of the cast as P in this context? I experimented with ...

Encountered an import failure with fs in Typescript @types/node

In my Typescript project, I am attempting to read a file using @types/node instead of typings. Although there are no compile errors, the debugger indicates that fs is undefined. What could I have overlooked? test.ts import * as fs from 'fs'; f ...

Discover the geolocation data for post code 0821 exclusively in Australia using Google Maps Geocoding

I'm having trouble geocoding the Australian postcode 0821. It doesn't seem to reliably identify this postcode as being located within the Northern Territory, unlike 0820 and 0822 which work fine. Here's an example of what I'm doing: ...

Create attributes that share the identical name as certain properties of the parent class

Upon extending a module, I have encountered an issue related to declaring private properties. Specifically, when I attempt to declare a method like init() as private, an error message is generated: Types have separate declarations of a private property ...

Utilizing Angular 2's NgFor directive in SVG Elements

I want to use ngFor to draw an SVG Element that consists of lines. I am struggling with the implementation and need some help fixing the code. Here is what I have so far: my-component.js: import {Component} from 'angular2/core'; @Component({ ...

What is the process for performing type checking on an array variable designated as "as const"?

Check out this code snippet: export type Types = 'a' | 'b'; export type MyPartials = { readonly [P in keyof Types]?: number; }; export interface MyI { readonly name: string; readonly myPartials: MyPartials; } export const myI ...

How to Delete an Item from an Array in BehaviorSubject Using Angular/Typescript

I have encountered an issue while trying to delete a specific element from my array upon user click. Instead of removing the intended item only, it deletes all elements in the array. I attempted to use splice method on the dataService object, but I'm ...