The rest of the owl: Knockout BindingHandlers with Typescript?

匿名 (未验证) 提交于 2019-12-03 02:31:01

问题:

I am trying in earnest to follow the accepted answer for this. I'm using Knockout, Typescript, MVC, VS2017 and node modules for most of my packages. The problem I'm having is that the binding does not get called but don't have any build errors.

provide a definition file (say myBindings.d.ts)

add the following code

  interface KnockoutBindingHandlers {         csharpTypes: KnockoutBindingHandler;     }

Reference this definition file in your extensions.ts file


Thus I created a customKoBindings.d.ts like this.

/// <reference path="../../node_modules/@types/knockout/index.d.ts" />  interface KnockoutBindingHandlers {     dataTablesForEach: KnockoutBindingHandler; }

I try to apply the binding in my cshtml. Do I need to pull in the ko.bindingHandler into my ViewModel in some way for it to be available for the view?

<table style="width: 100%" id="copyEmpTrainingSearchResultsTable" class="display" cellspacing="0">                                                 <thead>                                                     <tr>                                                         <th data-bind="sort: { arr: employees, prop: 'firstName' }">First Name</th>                                                         <th data-bind="sort: { arr: employees, prop: 'lastName' }">Last Name</th>                                                         <th data-bind="sort: { arr: employees, prop: 'jobTitle' }">Job Title</th>                                                         <th data-bind="sort: { arr: employees, prop: 'primaryManager' }">Manager</th>                                                         <th data-bind="sort: { arr: employees, prop: 'department' }">Department</th>                                                         <th>Trainings</th>                                                     </tr>                                                 </thead>                                                 <tbody data-bind="dataTablesForEach: {data: trainingEmployeeSearchResults, dataTableOptions: {}}">                                                     <tr>                                                         <td data-bind="text: firstName"></td>                                                         <td data-bind="text: lastName"></td>                                                         <td data-bind="text: jobTitle"></td>                                                         <td data-bind="text: primaryManager"></td>                                                         <td data-bind="text: department"></td>                                                         <td><button data-bind="click:$parent.seeTrainings"><i class="fa fa-eye"></i></button></td>                                                     </tr>                                                 </tbody>                                             </table>

The answer says to add the binding to extensions.ts, so I created a new file. Binding code comes from here. How would I reference the interface I created? What should be pointing to this file?

extensions.ts

import * as ko from "knockout" import * as $ from "jquery";  export class KnockoutExtensions {     // Constructor     constructor() {         ko.bindingHandlers.dataTablesForEach = {             page: 0,             init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {                 console.log("init for dataTablesForEach");                 var options = ko.unwrap(valueAccessor());                 ko.unwrap(options.data);                 if (options.dataTableOptions.paging) {                     valueAccessor().data.subscribe(function (changes) {                         var table = $(element).closest('table').DataTable();                         ko.bindingHandlers.dataTablesForEach.page = table.page();                         table.destroy();                     }, null, 'arrayChange');                 }                 var nodes = Array.prototype.slice.call(element.childNodes, 0);                 ko.utils.arrayForEach(nodes, function (node: Node) {                     if (node && node.nodeType !== 1) {                         node.parentNode.removeChild(node);                     }                 });                 return ko.bindingHandlers.foreach.init(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext);             },             update: function (element, valueAccessor, allBindings, viewModel, bindingContext) {                 console.log("update for dataTablesForEach");                 var options = ko.unwrap(valueAccessor()),                     key = 'DataTablesForEach_Initialized';                 ko.unwrap(options.data);                 var table;                 if (!options.dataTableOptions.paging) {                     table = $(element).closest('table').DataTable();                     table.destroy();                 }                 ko.bindingHandlers.foreach.update(element, valueAccessor, allBindings, viewModel, bindingContext);                 table = $(element).closest('table').DataTable(options.dataTableOptions);                 if (options.dataTableOptions.paging) {                     if (table.page.info().pages - ko.bindingHandlers.dataTablesForEach.page == 0)                         table.page(--ko.bindingHandlers.dataTablesForEach.page).draw(false);                     else                         table.page(ko.bindingHandlers.dataTablesForEach.page).draw(false);                 }                 if (!ko.utils.domData.get(element, key) && (options.data || options.length))                     ko.utils.domData.set(element, key, true);                 return { controlsDescendantBindings: true };             }         };      } }

Update:

In the DefinitelyTyped documentation's test they just do this, which I've now tried in the constructor of my viewModel but init and update still are not called:

 (<any>ko.bindingHandlers).countInits = { init: function() { initCalls++ } };

Update 2:

I have not used requireJS in this project. Is it needed for linking the KnockoutBindingHandler in?


Update 3:

After reviewing this article, I've attempted to reference the above customKoBindings.d.ts with the node modules reference in my tsconfig.json. This did not it fix either.

{   "compilerOptions": {     "outDir": "./wwwroot/build/",     "noImplicitAny": false,     "noEmitOnError": true,     "removeComments": false,     "sourceMap": true,     "target": "es6",     "module": "amd",     "moduleResolution": "node"   },   "files": [     "./Scripts/Common/customKoBindings.d.ts"   ],   "exclude": [     "node_modules",     "wwwroot"   ] }

Update Lost Count: It works!

added this to the top of extensions.ts:

/// <reference path="./customKoBindings.d.ts" />

in my main.ts added this:

import { KnockoutExtensions} from "./Common/extensions" const koExt = new KnockoutExtensions();

回答1:

added this to the top of extensions.ts:

/// <reference path="./customKoBindings.d.ts" />

in my main.ts added this:

import { KnockoutExtensions} from "./Common/extensions" const koExt = new KnockoutExtensions();


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!