ko.mapping || Cannot read property 'fromJS' of undefined

1.1k views Asked by At

I am new at typescript. I've been trying to use knockout.mapping with it, however, i can't make it work.

I've installed the libraries of knockout and knockout.mapping, also the @types from the two libraries, and even in that way can't that work.

I am using typescript in a laravel project and i am using laravel mix to generate the javascript files.

I got the next snippet:

///<reference path="../../../../node_modules/@types/jquery/index.d.ts"/>
///<reference path="../../../../node_modules/@types/knockout/index.d.ts"/>
///<reference path="../../../../node_modules/@types/knockout.mapping/index.d.ts"/>

import * as ko from "knockout";
import * as $ from "jquery";

$(function(){
    //this is only a test to check if ko.mapping exists on the ko object. And no, it doesn't appears.
    console.log("Message from jQuery Done", (ko));
});

class MyModel {
    _data: any;
    constructor(the_data: object)
    {
        let self = this;
        let example_observable = ko.observable(); //This is fine

        ko.mapping.fromJS(the_data, self._data); // This fails with the error -> Cannot read property 'fromJS' of undefined
    }
}

let myModel = new MyModel({"x": "y"});
ko.applyBindings(myModel);

My package.json include the knockout and knockout.mapping dependencies.

    "@types/jquery": "^3.3.6",
    "@types/knockout": "^3.4.58",
    "@types/knockout.mapping": "^2.0.33",
    "ajv": "^6.5.2",
    "knockout": "^3.4.2",
    "knockout.mapping": "^2.4.3",

I don't understand what i am doing wrong.

I appreciate any help.

Thanks in advance.

2

There are 2 answers

0
Dilakv On BEST ANSWER

This work for me. Maybe i am applying a bad solution, but definitely it work.

My problem was with "laravel mix".

In the webpackconfig i have to add the next one:

mix.webpackConfig({   
    //...
    externals: { // I supossed any "global" libraries goes here.
        'knockout': 'ko'
    }
    //...
});

In my HTML have to add:

<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.js"></script>

And, voilá!

I did try mix.autoload and didn't work, but maybe because i don't know how to use it.

Let me know if this is a stupid answer. I will unmark it.

1
Laurence Frost On

It looks like you might not actually be loading the Knockout mapping script into the browser. It's not part of the Knockout core - it's a separate library.

You can grab it from here: https://www.npmjs.com/package/knockout-mapping

You could need to include that in your page/package/bundle. Can you check if it's being included? You reference the types, but that doesn't mean that the resulting page or bundle will automatically have access to the mapping library.

As a quick diagnostic, try referencing it manually in a script tag from a CDN:

<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.js"></script>

Also just a pointer - you don't need to do this:

let self = this;

TypeScript handles the scoping of "this" much better, so you can reference "this" directly.