(() => { 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; }, originalChildNodes = [...ko.virtualElements.childNodes(element)]; 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 new 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 new Error('Unknown component \'' + componentName + '\''); } // cloneTemplateIntoElement var template = componentDefinition['template']; if (!template) { throw new Error('Component \'' + componentName + '\' has no template'); } ko.virtualElements.setDomNodeChildren(element, ko.utils.cloneNodes(template)); currentViewModel = componentDefinition['createViewModel'](componentParams, { 'element': element, 'templateNodes': originalChildNodes }); ko.applyBindingsToDescendants(asyncContext['createChildContext'](currentViewModel, { 'extend': ctx => { ctx['$component'] = currentViewModel; ctx['$componentTemplateNodes'] = originalChildNodes; } }), element); } }); }, { disposeWhenNodeIsRemoved: element }); return { 'controlsDescendantBindings': true }; } }; ko.virtualElements.allowedBindings['component'] = true; })();