UNPKG

angular2

Version:

Angular 2 - a web framework for modern web apps

290 lines 16.5 kB
'use strict';var __extends = (this && this.__extends) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { if (typeof Reflect === "object" && typeof Reflect.decorate === "function") return Reflect.decorate(decorators, target, key, desc); switch (arguments.length) { case 2: return decorators.reduceRight(function(o, d) { return (d && d(o)) || o; }, target); case 3: return decorators.reduceRight(function(o, d) { return (d && d(target, key)), void 0; }, void 0); case 4: return decorators.reduceRight(function(o, d) { return (d && d(target, key, o)) || o; }, desc); } }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var __param = (this && this.__param) || function (paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } }; var di_1 = require('angular2/src/core/di'); var lang_1 = require('angular2/src/facade/lang'); var exceptions_1 = require('angular2/src/facade/exceptions'); var viewModule = require('./view'); var view_ref_1 = require('./view_ref'); var api_1 = require('angular2/src/core/render/api'); var view_manager_utils_1 = require('./view_manager_utils'); var view_pool_1 = require('./view_pool'); var view_listener_1 = require('./view_listener'); var profile_1 = require('../profile/profile'); var proto_view_factory_1 = require('./proto_view_factory'); /** * Service exposing low level API for creating, moving and destroying Views. * * Most applications should use higher-level abstractions like {@link DynamicComponentLoader} and * {@link ViewContainerRef} instead. */ var AppViewManager = (function () { function AppViewManager() { } /** * Returns the {@link ElementRef} that makes up the specified Host View. */ AppViewManager.prototype.getHostElement = function (hostViewRef) { var hostView = view_ref_1.internalView(hostViewRef); if (hostView.proto.type !== viewModule.ViewType.HOST) { throw new exceptions_1.BaseException('This operation is only allowed on host views'); } return hostView.elementRefs[hostView.elementOffset]; }; return AppViewManager; })(); exports.AppViewManager = AppViewManager; var AppViewManager_ = (function (_super) { __extends(AppViewManager_, _super); function AppViewManager_(_viewPool, _viewListener, _utils, _renderer, _protoViewFactory) { _super.call(this); this._viewPool = _viewPool; this._viewListener = _viewListener; this._utils = _utils; this._renderer = _renderer; /** @internal */ this._createRootHostViewScope = profile_1.wtfCreateScope('AppViewManager#createRootHostView()'); /** @internal */ this._destroyRootHostViewScope = profile_1.wtfCreateScope('AppViewManager#destroyRootHostView()'); /** @internal */ this._createEmbeddedViewInContainerScope = profile_1.wtfCreateScope('AppViewManager#createEmbeddedViewInContainer()'); /** @internal */ this._createHostViewInContainerScope = profile_1.wtfCreateScope('AppViewManager#createHostViewInContainer()'); /** @internal */ this._destroyViewInContainerScope = profile_1.wtfCreateScope('AppViewMananger#destroyViewInContainer()'); /** @internal */ this._attachViewInContainerScope = profile_1.wtfCreateScope('AppViewMananger#attachViewInContainer()'); /** @internal */ this._detachViewInContainerScope = profile_1.wtfCreateScope('AppViewMananger#detachViewInContainer()'); this._protoViewFactory = _protoViewFactory; } AppViewManager_.prototype.getViewContainer = function (location) { var hostView = view_ref_1.internalView(location.parentView); return hostView.elementInjectors[location.boundElementIndex] .getViewContainerRef(); }; AppViewManager_.prototype.getNamedElementInComponentView = function (hostLocation, variableName) { var hostView = view_ref_1.internalView(hostLocation.parentView); var boundElementIndex = hostLocation.boundElementIndex; var componentView = hostView.getNestedView(boundElementIndex); if (lang_1.isBlank(componentView)) { throw new exceptions_1.BaseException("There is no component directive at element " + boundElementIndex); } var binderIdx = componentView.proto.variableLocations.get(variableName); if (lang_1.isBlank(binderIdx)) { throw new exceptions_1.BaseException("Could not find variable " + variableName); } return componentView.elementRefs[componentView.elementOffset + binderIdx]; }; AppViewManager_.prototype.getComponent = function (hostLocation) { var hostView = view_ref_1.internalView(hostLocation.parentView); var boundElementIndex = hostLocation.boundElementIndex; return this._utils.getComponentInstance(hostView, boundElementIndex); }; AppViewManager_.prototype.createRootHostView = function (hostProtoViewRef, overrideSelector, injector) { var s = this._createRootHostViewScope(); var hostProtoView = view_ref_1.internalProtoView(hostProtoViewRef); this._protoViewFactory.initializeProtoViewIfNeeded(hostProtoView); var hostElementSelector = overrideSelector; if (lang_1.isBlank(hostElementSelector)) { hostElementSelector = hostProtoView.elementBinders[0].componentDirective.metadata.selector; } var renderViewWithFragments = this._renderer.createRootHostView(hostProtoView.render, hostProtoView.mergeInfo.embeddedViewCount + 1, hostElementSelector); var hostView = this._createMainView(hostProtoView, renderViewWithFragments); this._renderer.hydrateView(hostView.render); this._utils.hydrateRootHostView(hostView, injector); return profile_1.wtfLeave(s, hostView.ref); }; AppViewManager_.prototype.destroyRootHostView = function (hostViewRef) { // Note: Don't put the hostView into the view pool // as it is depending on the element for which it was created. var s = this._destroyRootHostViewScope(); var hostView = view_ref_1.internalView(hostViewRef); this._renderer.detachFragment(hostView.renderFragment); this._renderer.dehydrateView(hostView.render); this._viewDehydrateRecurse(hostView); this._viewListener.onViewDestroyed(hostView); this._renderer.destroyView(hostView.render); profile_1.wtfLeave(s); }; AppViewManager_.prototype.createEmbeddedViewInContainer = function (viewContainerLocation, index, templateRef) { var s = this._createEmbeddedViewInContainerScope(); var protoView = view_ref_1.internalProtoView(templateRef.protoViewRef); if (protoView.type !== viewModule.ViewType.EMBEDDED) { throw new exceptions_1.BaseException('This method can only be called with embedded ProtoViews!'); } this._protoViewFactory.initializeProtoViewIfNeeded(protoView); return profile_1.wtfLeave(s, this._createViewInContainer(viewContainerLocation, index, protoView, templateRef.elementRef, null)); }; AppViewManager_.prototype.createHostViewInContainer = function (viewContainerLocation, index, protoViewRef, imperativelyCreatedInjector) { var s = this._createHostViewInContainerScope(); var protoView = view_ref_1.internalProtoView(protoViewRef); if (protoView.type !== viewModule.ViewType.HOST) { throw new exceptions_1.BaseException('This method can only be called with host ProtoViews!'); } this._protoViewFactory.initializeProtoViewIfNeeded(protoView); return profile_1.wtfLeave(s, this._createViewInContainer(viewContainerLocation, index, protoView, viewContainerLocation, imperativelyCreatedInjector)); }; /** * * See {@link AppViewManager#destroyViewInContainer}. * @internal */ AppViewManager_.prototype._createViewInContainer = function (viewContainerLocation, index, protoView, context, imperativelyCreatedInjector) { var parentView = view_ref_1.internalView(viewContainerLocation.parentView); var boundElementIndex = viewContainerLocation.boundElementIndex; var contextView = view_ref_1.internalView(context.parentView); var contextBoundElementIndex = context.boundElementIndex; var embeddedFragmentView = contextView.getNestedView(contextBoundElementIndex); var view; if (protoView.type === viewModule.ViewType.EMBEDDED && lang_1.isPresent(embeddedFragmentView) && !embeddedFragmentView.hydrated()) { // Case 1: instantiate the first view of a template that has been merged into a parent view = embeddedFragmentView; this._attachRenderView(parentView, boundElementIndex, index, view); } else { // Case 2: instantiate another copy of the template or a host ProtoView. // This is a separate case // as we only inline one copy of the template into the parent view. view = this._createPooledView(protoView); this._attachRenderView(parentView, boundElementIndex, index, view); this._renderer.hydrateView(view.render); } this._utils.attachViewInContainer(parentView, boundElementIndex, contextView, contextBoundElementIndex, index, view); this._utils.hydrateViewInContainer(parentView, boundElementIndex, contextView, contextBoundElementIndex, index, imperativelyCreatedInjector); return view.ref; }; /** @internal */ AppViewManager_.prototype._attachRenderView = function (parentView, boundElementIndex, index, view) { var elementRef = parentView.elementRefs[boundElementIndex]; if (index === 0) { this._renderer.attachFragmentAfterElement(elementRef, view.renderFragment); } else { var prevView = parentView.viewContainers[boundElementIndex].views[index - 1]; this._renderer.attachFragmentAfterFragment(prevView.renderFragment, view.renderFragment); } }; AppViewManager_.prototype.destroyViewInContainer = function (viewContainerLocation, index) { var s = this._destroyViewInContainerScope(); var parentView = view_ref_1.internalView(viewContainerLocation.parentView); var boundElementIndex = viewContainerLocation.boundElementIndex; this._destroyViewInContainer(parentView, boundElementIndex, index); profile_1.wtfLeave(s); }; // TODO(i): refactor detachViewInContainer+attachViewInContainer to moveViewInContainer AppViewManager_.prototype.attachViewInContainer = function (viewContainerLocation, index, viewRef) { var s = this._attachViewInContainerScope(); var view = view_ref_1.internalView(viewRef); var parentView = view_ref_1.internalView(viewContainerLocation.parentView); var boundElementIndex = viewContainerLocation.boundElementIndex; // TODO(tbosch): the public methods attachViewInContainer/detachViewInContainer // are used for moving elements without the same container. // We will change this into an atomic `move` operation, which should preserve the // previous parent injector (see https://github.com/angular/angular/issues/1377). // Right now we are destroying any special // context view that might have been used. this._utils.attachViewInContainer(parentView, boundElementIndex, null, null, index, view); this._attachRenderView(parentView, boundElementIndex, index, view); return profile_1.wtfLeave(s, viewRef); }; // TODO(i): refactor detachViewInContainer+attachViewInContainer to moveViewInContainer AppViewManager_.prototype.detachViewInContainer = function (viewContainerLocation, index) { var s = this._detachViewInContainerScope(); var parentView = view_ref_1.internalView(viewContainerLocation.parentView); var boundElementIndex = viewContainerLocation.boundElementIndex; var viewContainer = parentView.viewContainers[boundElementIndex]; var view = viewContainer.views[index]; this._utils.detachViewInContainer(parentView, boundElementIndex, index); this._renderer.detachFragment(view.renderFragment); return profile_1.wtfLeave(s, view.ref); }; /** @internal */ AppViewManager_.prototype._createMainView = function (protoView, renderViewWithFragments) { var mergedParentView = this._utils.createView(protoView, renderViewWithFragments, this, this._renderer); this._renderer.setEventDispatcher(mergedParentView.render, mergedParentView); this._viewListener.onViewCreated(mergedParentView); return mergedParentView; }; /** @internal */ AppViewManager_.prototype._createPooledView = function (protoView) { var view = this._viewPool.getView(protoView); if (lang_1.isBlank(view)) { view = this._createMainView(protoView, this._renderer.createView(protoView.render, protoView.mergeInfo.embeddedViewCount + 1)); } return view; }; /** @internal */ AppViewManager_.prototype._destroyPooledView = function (view) { var wasReturned = this._viewPool.returnView(view); if (!wasReturned) { this._viewListener.onViewDestroyed(view); this._renderer.destroyView(view.render); } }; /** @internal */ AppViewManager_.prototype._destroyViewInContainer = function (parentView, boundElementIndex, index) { var viewContainer = parentView.viewContainers[boundElementIndex]; var view = viewContainer.views[index]; this._viewDehydrateRecurse(view); this._utils.detachViewInContainer(parentView, boundElementIndex, index); if (view.viewOffset > 0) { // Case 1: a view that is part of another view. // Just detach the fragment this._renderer.detachFragment(view.renderFragment); } else { // Case 2: a view that is not part of another view. // dehydrate and destroy it. this._renderer.dehydrateView(view.render); this._renderer.detachFragment(view.renderFragment); this._destroyPooledView(view); } }; /** @internal */ AppViewManager_.prototype._viewDehydrateRecurse = function (view) { if (view.hydrated()) { this._utils.dehydrateView(view); } var viewContainers = view.viewContainers; var startViewOffset = view.viewOffset; var endViewOffset = view.viewOffset + view.proto.mergeInfo.viewCount - 1; var elementOffset = view.elementOffset; for (var viewIdx = startViewOffset; viewIdx <= endViewOffset; viewIdx++) { var currView = view.views[viewIdx]; for (var binderIdx = 0; binderIdx < currView.proto.elementBinders.length; binderIdx++, elementOffset++) { var vc = viewContainers[elementOffset]; if (lang_1.isPresent(vc)) { for (var j = vc.views.length - 1; j >= 0; j--) { this._destroyViewInContainer(currView, elementOffset, j); } } } } }; AppViewManager_ = __decorate([ di_1.Injectable(), __param(4, di_1.Inject(di_1.forwardRef(function () { return proto_view_factory_1.ProtoViewFactory; }))), __metadata('design:paramtypes', [view_pool_1.AppViewPool, view_listener_1.AppViewListener, view_manager_utils_1.AppViewManagerUtils, api_1.Renderer, Object]) ], AppViewManager_); return AppViewManager_; })(AppViewManager); exports.AppViewManager_ = AppViewManager_; //# sourceMappingURL=view_manager.js.map