Hi guys, I've got an issue with my angular application, I've got a form which is meant to create a new record (object) and push this object into an array.
My set up is the following:
I have a book.component.ts whic contains an array of IBooks as such:

books: IBook[] = [
        {
            "bookID":356,
            "bookAuthor":"John Beck",
            "bookTitle":"The story of my life",
            "location":"Shelf downstairs",
            "medium":"paper",
            "notes":""
        },
        {
            "bookID":900,
            "bookAuthor":"Jack Mills",
            "bookTitle":"They",
            "location":"Shelf downstairs",
            "medium":"PDF",
            "notes":"This is on my laptop and phone"
        }
    ];

This file also contains the static method

static createNewRecord($record): void{
        console.log("createNewRecord() called");
        console.log($record);
        this.books.push($record);
        console.log($record);
      //  $event.preventDefault();
    }

This method is static because it gets called from another component - the book-form.component - which is essentially a form which allow users to create a new books' object. The idea is that when the users submits the form the createNewRecord is called and adds the record to the books array. Now, when I run the application the compiler tells me that
"books.component.ts (51,14): Property 'books' does not exist on type 'typeof BooksComponent'." which kind of makes sense because I'm trying to access a non-static member (books) from a static method createNewRecord. My question is, how would I get around that?
Like I said the reason why I made that method static is because I needed to access it from another component.
I suppose I could make the array static too, but I'm not sure that's the right way to go. What do you guys think?

Recommended Answers

All 5 Replies

If you're thinking in OO then static is generally NOT the way.
In general, if you have a form and someunderlying data model (the array in this case?) then the pattern to use is:

Create an instance of the data model
Pass it to the form instance when that is created
The form instance can now use the data model's public methods to add/delete/update that instance of data model.

ps: Although you could just treat the array as the data model, that would create a tight linkage between the form and the data model's internal structure. Suppose later you had some reason to use a List instead? Or maybe later adding a Book would also trigger some other actions or updates? In general it would be cleaner to encapsulate the array in some class (eg "Library") with public methods for addBook etc. Pass the Library object to the form and keep its implementation private.

thanks, yes I think it makes sense although ultimately I want that array to be replaced by data that comes from a database. In any case, in terms of code structure, you're saying to have like two classes, one like Book like

export class Book{
    private _bookID: number;
    private _bookAuthor: string;
    private _bookTitle: string;
    private _location: string;
    private _medium: string;
    private _notes: string;

    public set bookID(bookID: number){
        this._bookID = bookID;
    }...

and one Library like

//import {Book} from './book';

    export class Library{

      private _books: Book[];
      public get books(){
        return this._books;
      }

      public addBook(){
      //// TODO: 
      }
      public removeBook(){
      //// TODO: 

is that what you meant?

Can't commernt on the detailed code, but yes, that's the structure I would use.

ultimately I want that array to be replaced by data that comes from a database

That really clinches it. Unless you want all kinds of pain re-writing of code you must encapsulate the way the Books are stored and hide the implementation.

Right, so I followed your advice and now I have this structure:
Library.ts:
-Contains an array of Book and add, remove and edit book;
Book.ts:
-Contains the properties of the book, author, title etc with setters and getters
book-form.component:
-This component handles the logic of the form submission. When the form is submitted the data is passed to it and this component uses the form data to create a Book object and to stash it into the array of Book
So far so good.
I then have a separate book.component which handles the dispay of the books in a table. This table has the records but also the remove and edit buttons. And this is where the problems start. Somehow I have to be able to call the remove and edit method which are in the Library.ts class from here, but the object of type Library is only created in the other component, so is there a way to share that Library object so I can access it from here too?

Library is the top level of the data model. You create that before you start any GUI. You may need to access a database or something as part of that. Then you pass that Library object to every GUI form when the form is created. Eg If you want to display the books in a table, you pass the Library object to the table form. The table form can then query the Library object to get all the Books in it. (So you need another public method in Library that will return all the Books, or (probably better if there a lots of books) an Iterator<Book> that iterates through all the books, or maybe even a search method)

book-form.component: ... this component uses the form data to create a Book object and to stash it into the array of Book

A good example of of Controller (as in MVC) class!
ps: I hope that's not literally what you do. It should say
this component uses the form data to create a Book object which it passes to the Library's addBook method.
Never stop thinking "what will happen when I replace the array with an SQL database? How can I minimise the impact on the rest of my code?"

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.