Bourni
Bourni

Reputation: 45

Typescript Cannot push to knockoutObservableArray because undefined even after initilize

I'm using asp.net MVC 5 with typescript. In my viewmodel im trying to push my data receive in ajax call from my api to my knockoutObservable array. Even when my array is initilize(or at least I think it should be).

Errr : TypeError: Cannot read property 'push' of undefined

Here is my code :

module Models {

export class ReservationDay {

    date: KnockoutObservable<Date>;
    place: KnockoutObservable<string>;
    avaibleSlots: KnockoutObservable<number>;
    instructorId: KnockoutObservable<string>;

    constructor(date: Date, place: string, avaibleSlots: number, instructorId: string) {
        this.date = ko.observable(date);
        this.place = ko.observable(place);
        this.avaibleSlots = ko.observable(avaibleSlots);
        this.instructorId = ko.observable(instructorId);
    }

  }
}


module ViewModel {
    import ReservationDay = Models.ReservationDay;

export class Calendar {


    public days: KnockoutObservableArray<ReservationDay> = ko.observableArray<ReservationDay>();

    constructor() {
        this.getMonthCalendar(new Date());
    }


getMonthCalendar(date: Date) {
        var month = date.getMonth() + 1;
        $.ajax({
            url: 'myApiUrl' + month,
            type: 'GET',
            dataType: 'json',
            async: false,
            success(data, textStatus, xhr) {
                if (data.length > 0) {
                    for (var i = 0; i < data.length; i++) {
                        console.log(this.days); // here is undefined
                        this.days.push(new ReservationDay(data[i].date,data[i].place,data[i].avaibleSlots, data[i].instructorId)); // in this line : error  : TypeError: Cannot read property 'push' of undefined
                    }
                    console.log("ajax done.");

                }
            },
            error(xhr, textStatus, errorThrown) {
                console.log('Error in Operation');
            }
        });
    }

and here is my view :

@section Scripts{
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/knockout")
@Scripts.Render("~/bundles/bootstrap")
@Scripts.Render("~/bundles/calendar")




<script type="text/javascript">
    $(function () {
        var vm = new ViewModel.Calendar(@Model);
        ko.applyBindings(vm);
    });
</script>

}

And also another question, can anyone explain me how to use the ReservationDay.ts class located in other folder not in the file that has a viewmodel like above. My folders img

Thank you in advance!

Upvotes: 0

Views: 129

Answers (1)

adiga
adiga

Reputation: 35202

Because this inside the ajax success doesn't refer to an instance of Calendar but the ajax settings object.

You can fix this by adding a reference to the Calendar instance outside ajax:

getMonthCalendar(date: Date) {
    var self = this;

    $.ajax({
      ........
      ........
      success: (data, textStatus, xhr) => {
        if (data.length > 0) {
         for (var i = 0; i < data.length; i++) {
            self.days.push((new ReservationDay(data[i].date,data[i].place,data[i].avaibleSlots, data[i].instructorId));
          }
        }
      }
    })
}

Or

you can use the context key in ajax settings. This will set the custom context of all ajax callbacks.

$.ajax({
      url: 'myApiUrl' + month,
      type: 'GET',
      context: this,
      success: (data, textStatus, xhr) => {
         console.log(this.days); // refers to the "Calendar" instance
      }
      ....
  });

Here's a fiddle for testing


And to import the ReservationDay class in your structure you can do:

import {ReservationDay} from "../viewmodel/calendar"

Upvotes: 1

Related Questions