UNPKG

@openui5/sap.ui.core

Version:

OpenUI5 Core Library sap.ui.core

278 lines (255 loc) 10.6 kB
/*! * OpenUI5 * (c) Copyright 2009-2021 SAP SE or an SAP affiliate company. * Licensed under the Apache License, Version 2.0 - see LICENSE.txt. */ // Provides control sap.ui.core.mvc.JSView. sap.ui.define([ './View', './JSViewRenderer', 'sap/base/util/extend', 'sap/base/util/merge', 'sap/ui/base/ManagedObject', 'sap/ui/core/library', 'sap/base/Log' ], function(View, JSViewRenderer, merge, extend, ManagedObject, library, Log) { "use strict"; /** * Constructor for a new <code>JSView</code>. * * <strong>Note:</strong> Application code shouldn't call the constructor directly, but rather use the factory * {@link sap.ui.core.mvc.JSView.create JSView.create} or {@link sap.ui.core.mvc.View.create View.create} * with type {@link sap.ui.core.mvc.ViewType.JS JS}. The factory simplifies asynchronous loading of a view * and future features might be added to the factory only. * * @param {string} [sId] id for the new control, generated automatically if no id is given * @param {object} [mSettings] initial settings for the new control * * @class * A View defined/constructed by JavaScript code. * @extends sap.ui.core.mvc.View * @version 1.87.1 * * @public * @alias sap.ui.core.mvc.JSView * @ui5-metamodel This control/element also will be described in the UI5 (legacy) designtime metamodel */ var JSView = View.extend("sap.ui.core.mvc.JSView", /** @lends sap.ui.core.mvc.JSView.prototype */ { metadata : { library : "sap.ui.core" }, renderer: JSViewRenderer }); /** * Map of already registered JavaScript views (pseudo classes), keyed by their name. * * When a new JSView definition is registered for some name, the definition object * is stored in this map, keyed by that name. * * When a new instance of JSView is created for an already registered view name (class), * then all properties from the corresponding definition object in this map are copied to * the new instance of JSView. * * There's currently no API to remove view definitions from this map. * * @type Object.<string,Object> * @private */ var mRegistry = {}; /** * Flag for feature detection of asynchronous loading/rendering * @public * @since 1.30 */ JSView.asyncSupport = true; // shortcut for enum(s) var ViewType = library.mvc.ViewType; /** * Creates an instance of the view with the given name (and id). * * @param {object} oOptions An object containing the view configuration options. * @param {string} [oOptions.id] Specifies an ID for the view instance. If no ID is given, an ID will be generated. * @param {string} [oOptions.viewName] Name of the view. The view must still be defined using {@link sap.ui.jsview}. * @param {sap.ui.core.mvc.Controller} [oOptions.controller] Controller instance to be used for this view. * The given controller instance overrides the controller defined in the view definition. Sharing a controller instance * between multiple views is not supported. * @public * @static * @since 1.56.0 * @return {Promise<sap.ui.core.mvc.JSView>} A promise that resolves with the view instance */ JSView.create = function(oOptions) { var mParameters = merge({}, oOptions); //remove unsupported options: for (var sOption in mParameters) { if (sOption === 'definition' || sOption === 'preprocessors') { delete mParameters[sOption]; Log.warning("JSView.create does not support the options definition or preprocessor!"); } } mParameters.type = ViewType.JS; return View.create(mParameters); }; /** * Defines or creates an instance of a JavaScript view. * * The behavior of this method depends on the signature of the call and on the current context. * * <h3>View Definition</h3> * <pre> * sap.ui.jsview(sId, vView); * </pre> * Defines a view of the given name with the given implementation. <code>sId</code> must be the view's name, * <code>vView</code> must be an object and can contain implementations for any of the hooks provided by JSView. * * <h3>View Instantiation (deprecated)</h3> * <pre> * var oView = sap.ui.jsview(vView); * var oView = sap.ui.jsview(vView, bASync); * var oView = sap.ui.jsview(sId, vView); * var oView = sap.ui.jsview(sId, vView, bAsync); * </pre> * Creates an instance of the view with the given name (and id). If no view implementation has been defined * for that view name, a JavaScript module with the same qualified name and with suffix <code>.view.js</code> * will be loaded (required) and executed. The module should register a view definition on execution * (1st. variant above). * * If <code>sId</code> is omitted, an ID will be created automatically. * * When <code>bAsync</code> has a truthy value, the view definition will be read asynchronously, if needed, * but the (incomplete) view instance will be returned immediately. * * <b>Note:</b> Using <code>sap.ui.jsview</code> for creating view instances has been deprecated, use * {@link sap.ui.core.mvc.JSView.create JSView.create} instead. <code>JSView.create</code> enforces * asynchronous loading and can be used via an AMD reference, it doesn't rely on a global name. * * <b>Note:</b> Any other call signature will lead to a runtime error. * * @param {string} [sId] id of the newly created view, only allowed for instance creation * @param {string | object} vView name or implementation of the view. * @param {boolean} [bAsync] defines how the view source is loaded and rendered later on * (only relevant for instantiation, ignored for everything else) * @public * @static * @deprecated Since 1.56, use {@link sap.ui.core.mvc.JSView.create JSView.create} to create view instances; * for defining JavaScript views, there's no substitute yet and <em>sap.ui.jsview</em> still has to be used * @return {sap.ui.core.mvc.JSView | undefined} the created JSView instance in the creation case, otherwise undefined * @ui5-global-only */ sap.ui.jsview = function(sId, vView, bAsync) { var fnLogDeprecation = function(sMethod) { Log[sMethod]( "Do not use deprecated view factory functions. " + "Use the static create function on the specific view module instead: [XML|JS|HTML|JSON]View.create().", "sap.ui.view", null, function () { return { type: "sap.ui.view", name: sId || (vView && vView.name) }; } ); }; if (vView && vView.async) { fnLogDeprecation("info"); } else { fnLogDeprecation("warning"); } return viewFactory.apply(this, arguments); }; /* * The old view factory implementation */ function viewFactory(sId, vView, bAsync) { var mSettings = {}, oView; if (vView && typeof (vView) == "string") { // instantiation sap.ui.jsview("id","name", [async]) mSettings.viewName = vView; if (typeof arguments[2] == "boolean") { mSettings.async = bAsync; } else if (typeof arguments[2] == "object") { // arguments[2] is somehow a controller mSettings.controller = arguments[2]; mSettings.async = !!arguments[3]; // optional } oView = new JSView(sId, mSettings); return oView; } else if (vView && typeof (vView) == "object") { // definition sap.ui.jsview("name",definitionObject) // sId is not given, but contains the desired value of sViewName mRegistry[sId] = vView; sap.ui.loader._.declareModule(sId.replace(/\./g, "/") + ".view.js"); Log.info("For defining views use JSView.extend instead."); } else if (arguments.length == 1 && typeof sId == "string" || arguments.length == 2 && typeof arguments[0] == "string" && typeof arguments[1] == "boolean") { // instantiation sap.ui.jsview("name", [async]) mSettings.viewName = arguments[0]; mSettings.async = !!arguments[1]; // optional /*** STEP 1: create View ***/ oView = mSettings.id ? new JSView(mSettings.id, mSettings) : new JSView(mSettings); /*** Step 3B and 4B (create and connect controller) happen in View ***/ return oView; } else { throw new Error("Wrong arguments ('" + sId + "', '" + vView + "')! Either call sap.ui.jsview([sId,] sViewName) to instantiate a View or sap.ui.jsview(sViewName, oViewImpl) to define a View type."); } } JSView.prototype.initViewSettings = function (mSettings) { var oPromise; // require view definition if not yet done... if (!mRegistry[mSettings.viewName]) { var sModuleName = mSettings.viewName.replace(/\./g, "/") + ".view"; if ( mSettings.async ) { oPromise = new Promise(function(resolve, reject) { sap.ui.require([sModuleName], resolve, reject); }); } else { sap.ui.requireSync(sModuleName); } } // extend 'this' with view from registry which should now or then be available if (mSettings.async) { return Promise.resolve(oPromise).then(function() { extend(this, mRegistry[mSettings.viewName]); }.bind(this)); } extend(this, mRegistry[mSettings.viewName]); }; JSView.prototype.onControllerConnected = function(oController) { // temporarily replace any preprocessors, e.g. from an enclosing JSON view ManagedObject.runWithPreprocessors(function() { this.applySettings({ content : this.createContent(oController) }); }, { // when auto prefixing is enabled, we add the prefix id: this.getAutoPrefixId() ? this.createId.bind(this) : undefined, settings: this._fnSettingsPreprocessor }, this); }; /** * A method to be implemented by JSViews, returning the flag whether to prefix * the IDs of controls automatically or not if the controls are created inside * the {@link sap.ui.core.mvc.JSView#createContent} function. By default this * feature is not activated. * * You can overwrite this function and return true to activate the automatic * prefixing. * * @since 1.15.1 * @return {boolean} true, if the controls IDs should be prefixed automatically * @protected */ JSView.prototype.getAutoPrefixId = function() { return false; }; /** * A method to be implemented by JSViews, returning the View UI. * While for declarative View types like XMLView or JSONView the user interface definition is declared in a separate file, * JSViews programmatically construct the UI. This happens in the createContent method which every JSView needs to implement. * The View implementation can construct the complete UI in this method - or only return the root control and create the rest of the UI lazily later on. * * @return {sap.ui.core.Control} a control or (typically) tree of controls representing the View user interface * @public * @name sap.ui.core.mvc.JSView#createContent * @function */ return JSView; });