Leverage the power of data binding in Typescript Ionic by exposing object functions

Is there a way to execute a function on a Typescript model object within an Ionic HTML template? Whenever I try to do so, it triggers an error message saying

self.context.$implicit.myFunctionName is not a function
.

In my Ionic2 app, I am aiming to showcase images from the Flickr API. To generate the URL for a Flickr photo, one needs to combine multiple data fields from the API response and add a specific suffix denoting the desired photo resolution. This task is accomplished through the getUrl function within the Photo model.

src/models/photo.ts

export class Photo {

    id: string;
    owner: string;
    secret: string;
    server: string;
    farm: number;
    title: string;
    url: string;

    // Retrieve the URL for the photo at the specified suffix size.
    // s - small square 75x75
    // q - large square 150x150
    // t - thumbnail, 100 on longest side
    // m - small, 240 on longest side
    // n - small, 320 on longest side
    // - - medium, 500 on longest side ... etc

    getUrl(suffix: string) {
        return 'https://farm' + this.farm +
            '.staticflickr.com/' + this.server +
            '/' + this.id + '_' + this.secret + '_' + suffix + '.jpg';
    }
}

The HTML template invokes getUrl('q') for each photo in the returned set.

 <div *ngFor="let photo of photos" class="photo-thumbnail">
    <img [src]="photo.getUrl('q')" />
</div>

As a result, the following error emerges:

Uncaught Error: Error in ./PhotosPage class PhotosPage - inline template:13:9 caused by: self.context.$implicit.getUrl is not a function

Additional code:

src/pages/photos.ts

import { Component } from '@angular/core';

import { Photo } from '../../models/photo';
import { FlickrService } from '../../services/flickr.service'

@Component({
  selector: 'page-photos',
  templateUrl: 'photos.html'
})
export class PhotosPage {

  photos: Photo[];

  constructor(private flickrService: FlickrService) {

    // Receive photo data from Flickr (this function is operating as intended)
    flickrService.getPhotos().subscribe(photos => {
        this.photos = photos;
    });
  }
}

services/flickr.service.ts

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import { Observable } from 'rxjs/Rx';
import 'rxjs/add/operator/map';

import { Photo } from '../models/photo';

@Injectable()
export class FlickrService {

    constructor(public http: Http){}

    // Fetch the initial 100 photos for a user (this function is functioning as expected)
    getPhotos(): Observable<Photo[]> {
        return this.http.get('https://api.flickr.com/path/to/api/call')
        .map(res => <Photo[]>res.json().photos.photo);
    }
}

Answer №1

Now, let's delve into the limitations of the Javascript language. The issue arises when retrieving photos from the server, as they are in the form of pure JSON objects. Unfortunately, JSON does not allow for the inclusion of function definitions, complicating the process. The casting here serves little purpose, as it is essentially removed during transpilation. Its presence primarily aids in enhancing the project's appearance and providing clarity to other developers. The getUrl function is designed for instance objects, yet the photos in the array do not match this criterion, rendering the casting ineffective.

  1. One approach is to iterate through the backend array and create new Photo instances for each photo. This involves manually instantiating each object, a somewhat cumbersome solution.

  2. Alternatively, a static function can be implemented to facilitate the creation of URLs for photos, offering a more streamlined approach than individual instance creation.

  3. Exploring external libraries specialized in serialization is a feasible but complex option.

I trust this guidance proves helpful in navigating these challenges. TypeScript shines in offering robust design-time support, although run-time functionality may be limited.

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

What is the best way to include a router-link in a button click event in Angular 8?

Can someone please help me with adding a routing function to a button in Angular? I have already included a (click) function on the button, but how do I actually make the function navigate within the home.ts component? <button class="navbut" (click)= ...

What is the best way to send requests to an API server without directly specifying the URL in the code?

As I work on implementing an app using Angular 2, I find myself needing to make requests to my API server. However, hardcoding the full URL in every request doesn't seem like a good idea since it's likely to change. While researching a solution, ...

When you use array[index] in a Reduce function, the error message "Property 'value' is not defined in type 'A| B| C|D'" might be displayed

Recently, I delved deep into TypeScript and faced a challenge while utilizing Promise.allSettled. My objective is to concurrently fetch multiple weather data components (such as hourly forecast, daily forecast, air pollution, UV index, and current weather ...

Encountering a Problem with TypeScript Decorators

I've been diving into TypeScript by working on TS-based Lit Elements and refactoring a small project of mine. However, I'm starting to feel frustrated because I can't seem to figure out what's wrong with this code. Even though it' ...

Activate expansive pop-up windows with primeng's dynamic dialog feature

In my Angular web application, I am using the PrimeNg modal extension to display modal popups. I have successfully passed a component to the modal service with the following code: const ref = this.dialogService.open(LogsComponent, { data: { ...

When using npm link, it searches for the module in the src directory rather than the dist directory

In my experience with Angular CLI Builder, I have implemented a custom builder to extend the asset configuration in angular.json for libraries that have their own assets. To manage my workspace, I utilized nrwl. I created an Angular CLI builder library an ...

Why does my export function get executed every time the TextInput changes?

Hey there, here is my React and TypeScript code. I'm wondering why the console.log statement gets called every time my text field changes... export default function TabOneScreen({ navigation, }) { const [out_1, set_out1] = useState('' ...

What are the steps to set up a dictionary with predetermined values?

My task is to create a pre-defined dictionary where the key represents a city and the value is an array of zones in that city. Here is my attempt: export const cityToZone: { [city: string]: Array<string> } = [ {city:'New York', [&apos ...

Excessive whitespace appearing on the right and bottom edges of the Angular application

I'm fairly new to web development, so this may be a silly question, but I really could use some help. I've created my first Angular app and noticed that there is a lot of white space on the right side of the landing page, as well as at the bottom ...

custom field component for react-hook-form

I have been working on creating a form field component that can be utilized at both the root form level and as a nested field. export type FirstNameField = { firstName: string; }; type GenericFormType<T, NS extends string | never = never> = NS ext ...

Preventing long int types from being stored as strings in IndexedDB

The behavior of IndexedDB is causing some unexpected results. When attempting to store a long integer number, it is being stored as a string. This can cause issues with indexing and sorting the data. For instance: const data: { id: string, dateCreated ...

Hovering over a table cell triggers a popup in Angular

Inserted a class into <td><span class="only-show-on-hover"></span></td> CSS code for the class td span.only-show-on-hover { visibility: hidden; } td:hover span.only-show-on-hover { visibility: visible; } Code for dialog box < ...

Utilize swipe gestures in tables with Angular and Ionic for enhanced user interaction

I'm working on creating a swiping functionality for table pagination. Swiping right will take you to the next page, while swiping left will move you back to the previous page. Here's the code snippet of my table: <table #tableElement id=&qu ...

TypeScript recursive object mapping utility

I am currently developing a type-safe object mapper in TypeScript. So far, I have successfully implemented this at a single level of depth using this playground. enum TransformerActions { Delete = 'delete', } type TransformerMap<S> = ...

How to retrieve the value of an input field in Angular 2/Typescript without using ngModel

Currently, I'm utilizing Typescript in conjunction with Angular2, mirroring the structure of the Angular2 Tour of Heroes guide. There is a specific input field that I aim to associate a change event with, triggering custom logic whenever the value wi ...

Exported data in Vue3 components cannot be accessed inside the component itself

Essentially, I'm working on creating a dynamic array in Vue3. Each time a button is clicked, the length of the array should increase. Below is the code snippet. <div class="package-item" v-for="n in arraySize"></div> e ...

Tips for incorporating the Sanitize library into Angular 6:

What is the most effective library for sanitization in Angular 6 to enhance security measures? Since injecting dependencies can be tricky, what are some recommended methods for implementing this in an Angular 6 project? ...

The CORS policy has blocked access to XMLHttpRequest because the 'Access-Control-Allow-Origin' header is missing on the requested resource

I encountered an issue where making a call from my Angular 7 application to my ASP.NET Web API resulted in an exception. When attempting to send an HTTP post request from Angular to an application running on a different port, a CORS policy error was thrown ...

Combining Rxjs map and filter to extract countries and their corresponding states from a JSON dataset

I have a unique dataset in JSON format that includes information about countries and states. For example: { "countries": [ { "id": 1, "name": "United States" }, { "id": 2, "name": "India" }], "states": [ { ...

Angular issue: Element 'mdb-select' is unrecognized

While working with Angular's MDB pro version, I encountered a peculiar error message: mdb-select is now a known element I suspect that I may have missed an import somewhere, but the specific one eludes me This snippet shows my component.html file: ...