(() => { var componentLoadingOperationUniqueId = 0; ko.bindingHandlers['component'] = { 'init': (element, valueAccessor, ignored1, ignored2, bindingContext) => { var currentViewModel, currentLoadingOperationId, afterRenderSub, disposeAssociatedComponentViewModel = () => { var currentViewModelDispose = currentViewModel && currentViewModel['dispose']; if (typeof currentViewModelDispose === 'function') { currentViewModelDispose.call(currentViewModel); } if (afterRenderSub) { afterRenderSub['dispose'](); } afterRenderSub = null; currentViewModel = null; // Any in-flight loading operation is no longer relevant, so make sure we ignore its completion currentLoadingOperationId = null; }; ko.virtualElements.emptyNode(element); ko.utils.domNodeDisposal['addDisposeCallback'](element, disposeAssociatedComponentViewModel); ko.computed(() => { var componentName = ko.utils.unwrapObservable(valueAccessor()), componentParams; if (typeof componentName !== 'string') { componentParams = ko.utils.unwrapObservable(componentName['params']); componentName = ko.utils.unwrapObservable(componentName['name']); } if (!componentName) { throw Error('No component name specified'); } var asyncContext = ko.bindingEvent.startPossiblyAsyncContentBinding(element, bindingContext); var loadingOperationId = currentLoadingOperationId = ++componentLoadingOperationUniqueId; ko['components'].get(componentName, componentDefinition => { // If this is the current load operation for this element if (currentLoadingOperationId === loadingOperationId) { // Clean up previous state disposeAssociatedComponentViewModel(); // Instantiate and bind new component. Implicitly this cleans any old DOM nodes. if (!componentDefinition) { throw Error('Unknown component \'' + componentName + '\''); } // cloneTemplateIntoElement var template = componentDefinition['template']; if (!template) { throw Error('Component \'' + componentName + '\' has no template'); } ko.virtualElements.setDomNodeChildren(element, ko.utils.cloneNodes(template)); currentViewModel = componentDefinition['createViewModel'](componentParams, { 'element': element }); ko.applyBindingsToDescendants(asyncContext['createChildContext'](currentViewModel, {}), element); } }); }, { disposeWhenNodeIsRemoved: element }); return { 'controlsDescendantBindings': true }; } }; ko.virtualElements.allowedBindings['component'] = true; })();