0

I am working with Javascript and Appdescriptors in JSON format. What I want to do is creating a instance of a Class, where the classname is saved as string in oModelConf[sModelName].type. If that is not the case I want to take "sap.ui.model.odata.ODataModel"

Related Question offers this solution:

function instantiate(className, args) {
    var o, f, c;
    c = window[className]; // get reference to class constructor function
    f = function(){}; // dummy function
    f.prototype = c.prototype; // reference same prototype
    o = new f(); // instantiate dummy function to copy prototype properties
    c.apply(o, args); // call class constructor, supplying new object as context
    o.constructor = c; // assign correct constructor (not f)
    return o;
}

This is not a very good solution I think.

EDIT It does not work for me because my class is not defined on window, so window[className] is undefined. I do not know where my function is defined in SAPUI5

A second Solution:

eval(`a = new ${oModelConf[sModelName].type || "sap.ui.model.odata.ODataModel"}(sServiceUrl, true);`);

This is not a better solution because we should not use eval().

Are there any better solutions?

EDIT2 Because of the url in pimskies answer I found an other solution:

Since window.sap.ui.model.odata.ODataModel is the same as sap.ui.model.odata.ODataModel and window.sap is the same as window[sap] I could take my string, and replace all . with ][, put the right brackets to front and end.

I will not code that because it is not a going solution.(I should not have coded the evalthing too...)

Community
  • 1
  • 1
inetphantom
  • 2,498
  • 4
  • 38
  • 61

3 Answers3

3

You could use jQuery.sap.getObject to access the class:

var ModelClass = jQuery.sap.getObject(oModelConf[sModelName].type || "sap.ui.model.odata.ODataModel");
var model = new ModelClass();

Edit: An other way (which i would recommend if you use AMD)

If you are using the modern AMD modules and you don't know if the module containing your class has already been loaded, you should use sap.ui.require() to load the module asynchronously. It requires the module to be specified via its unified resource name (the conversion is probably the most ugly part):

var className = oModelConf[sModelName].type || "sap.ui.model.odata.ODataModel";
var urn = className.replace(".", "/"); //Convert to unified resource name
sap.ui.require([urn],function(ModelClass){
  //This function is called when the module is available
  var model = new ModelClass();
  ...
});
schnoedel
  • 3,918
  • 1
  • 13
  • 17
  • I've just stumbled about dynamic model instantiation in the sap.ui.core.Component (the model type has been read from the manifest.json): [it uses jQuery.sap.getObject()](https://github.com/SAP/openui5/blob/rel-1.34/src/sap.ui.core/src/sap/ui/core/Component.js#L787) – schnoedel Mar 30 '16 at 20:00
  • I am doing exactly that instantiation. Because I am erlier than version 1.30, this gets not done automaticly, hop we will update soon.. It works like that thx! – inetphantom Apr 04 '16 at 09:34
0

Maybe map the string to a class?

function Foo() {
  console.log('new foo');
}

function Bar() {
  console.log('new bar');
}

var objects = {
    'foo': Foo,
  'bar': Bar
};

var cls = objects.foo || Bar;

new cls();

https://jsfiddle.net/ckd56d9v/1/

Or take a look at this answer: https://stackoverflow.com/a/9804142/5930258

Community
  • 1
  • 1
Pimmol
  • 1,871
  • 1
  • 8
  • 14
  • found something see my edit. Your first solution would work, but I do not know if there will ever come a new object (e.g `baz`) so this will need a lot of support which I do not want to – inetphantom Mar 24 '16 at 16:42
0

What not combine the two? Since window[className] is failing, replace it with oModelConf[className].type || sap.ui.model.odata.ODataModel...

function instantiate(className, args) {
    var o, f, c;
    c = oModelConf[className] || sap.ui.model.odata.ODataModel;
    f = function(){}; // dummy function
    f.prototype = c.prototype; // reference same prototype
    o = new f(); // instantiate dummy function to copy prototype properties
    c.apply(o, args); // call class constructor, supplying new object as context
    o.constructor = c; // assign correct constructor (not f)
    return o;
}
Aron Boyette
  • 887
  • 9
  • 12
  • `window[className]` is failing, because my className is not just an Object but a subproperty of a subproperty.. `window[class][name]` would work. – inetphantom Mar 24 '16 at 16:40