6

I am in the process of porting some javascript code to typescript and using requirejs. I have a config.ts:

//file config.ts
///<reference path="../require.d.ts" />
///<reference path="DataLayer.ts" />

require.config({
    baseUrl: '/scripts/App/',

    paths: {
        'jQuery': '/scripts/jquery-1.9.1',
        'ko': '/scripts/knockout-2.2.1',
        'signalR': "/scripts/jquery.signalR-1.0.1",
    },

    shim: {
        jQuery: {
            exports: '$'

        },
         signalR:{
            deps: ["jQuery"]
         },
         ko: {
             deps: ["jQuery"],
             exports: 'ko'
         }
    }
});

// load AMD module main.ts (compiled to main.js)
// and include shims $, _, Backbone

require(['DataLayer', 'signalR', 'ko'], (d ) => {
    alert('test');
    var app = new d.DataLayer();
    app.run();
  //  app.run();

});

it being loaded with:

<script data-main="/Scripts/App/config" type="text/javascript" src="~/scripts/require.js"></script>

Before i just had a scripttag on my page that executed the following:

ko.bindingHandlers.csharpTypes = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var value = valueAccessor();

        switch (value) {
            case 'System.Boolean':
                element.type = 'checkbox';
                break;
            case 'System.String':
                element.type = 'string';
                break;
            case 'System.DateTime':
                //$(element).replaceWith("<input placeholder='value' data-bind='value:value, uniqueId: name, csharpTypes:type'/>");
                element.type = 'datetime';
                break;
            default:
                element.type = 'number';
        }


    }

};

and the extension was added to knockout. I am not 100% sure where i would put this code right now? If its in the page, its loaded before knockout get loaded by requirejs. I assume i need to get it loaded with requirejs, i am just not sure about how i would do it. In a typescript class or maybe just in the config.ts ?

require(['DataLayer', 'signalR', 'ko'], (d ) => {
        alert('test');
        var app = new d.DataLayer();
        app.run();
      //  app.run();

    });

I have tried:

extensions.ts

     ///<reference path="knockout.d.ts" />    
    export class KnockoutExtenions {
        // Constructor
        constructor() {
            ko.bindingHandlers.csharpTypes = {
                init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
                    var value = valueAccessor();

                    switch (value) {
                        case 'System.Boolean':
                            element.type = 'checkbox';
                            break;
                        case 'System.String':
                            element.type = 'string';
                            break;
                        case 'System.DateTime':
                            //$(element).replaceWith("<input placeholder='value' data-bind='value:value, uniqueId: name, csharpTypes:type'/>");
                            element.type = 'datetime';
                            break;
                        default:
                            element.type = 'number';
                    }


                }

            };
      }
}

but it gives me a error on the csharpTypes of ko.bindinghandlers.

Poul K. Sørensen
  • 16,950
  • 21
  • 126
  • 283

1 Answers1

5

You can extend existing TypeScript interfaces out of the box. To define your own binding handlers, all you need to do is:

  1. provide a definition file (say myBindings.d.ts)
  2. add the following code

    interface KnockoutBindingHandlers {
        csharpTypes: KnockoutBindingHandler;
    }
    
  3. Reference this definition file in your extensions.ts file
thomaux
  • 19,133
  • 10
  • 76
  • 103
  • 1
    Cool i will try this when i get home. If two interfaces are defined with same name, they are simply merged ? – Poul K. Sørensen Apr 08 '13 at 21:30
  • 1
    Yes, indeed, it's not very well documented though. I'll try to find some references. – thomaux Apr 09 '13 at 06:24
  • Do you have to do this in a d.ts file for it to properly merge? I've tried it inline, right above the binding handler in the .ts file and it doesn't seem to work anymore on the latest version of typescript. It used to work in a previous version – Allen Rice Jun 04 '14 at 20:02
  • I haven't used TypeScript in a while, but if you try it online, in the playground, you can check if it works there. – thomaux Jun 04 '14 at 20:46
  • oh so frustrating, yep, to do this you have to put it in a .d.ts file for it to work. Weird that they removed the ability to do this inline. – Allen Rice Jun 05 '14 at 08:22
  • @AllenRice it's possible they did this to adhere to the ECMA6 standard, but luckily the work around isn't that hard :) – thomaux Jun 05 '14 at 09:18
  • 1
    Yep! I kind of like having it in a .d.ts file anyway, makes for a nice way to keep a record of all your custom bindings – Allen Rice Jun 05 '14 at 17:17
  • updated my previous question / answer about this, with the above information: http://stackoverflow.com/questions/16204142/how-do-i-define-a-knockout-binding-handler-in-typescript – Allen Rice Jun 05 '14 at 17:26
  • @thomaux, if you have some more details about how exactly to implement this, I'm very stuck and posted another question here: https://stackoverflow.com/questions/47876958/the-rest-of-the-owl-knockout-bindinghandlers-with-typescript (only just now have enough rep to post a comment) – azulBonnet Dec 19 '17 at 16:52