1
\$\begingroup\$

The context here is Backbone but it's a general question about dynamically creating javascript objects.

I would like to pass the name of a View ('ViewX') to be created, to a function which can then create the new ViewX()

How could I do this?

In my Backbone View I want to create a subView, the type of which depends on the Model I have used for the current View. At the moment I have an if-else structure (See Approach #1 in the example) which works, but is clunky and will be more clunky in future when I have more Model types.

I have tried some alternatives, including evaluation via the Function constructor (Approach #2), which gives 'string is not a function' error. In Approach #3, the View module I am passing as a parameter is not available in the current View's this namespace (I am using requirejs).

renderContentList: function() {

    var self = this;

    // Approach #1
    var setSidebarListCollectionView = function(type) {
       if (type === 'tags') {
           self.sidebarListCollectionView = new TagSidebarListCollectionView({
               collection: self.collection,
               tagCollection: self.tagCollection
           });
       } else {
           self.sidebarListCollectionView = new CardSidebarListCollectionView({
               collection: self.collection,
               tagCollection: self.tagCollection
           });
       }
    };
    /*
    // Approach #2
    var setSidebarListCollectionView = new Function('type', 'coll', 'tagColl', 'return new type({collection: coll, tagCollection: tagColl});');

    // Approach #3
    var setSidebarListCollectionView = function(type) {
        return new self[type]({
                        collection: self.collection,
                        tagCollection: self.tagCollection
                    });
    };
    */
    // reset it every time
    if (this.sidebarListCollectionView) {
        this.sidebarListCollectionView.remove();
    }
    if (this.model.get('activeSubTab') === 'tags') {
        // Approach #1
        setSidebarListCollectionView('tags');
        // Approach #2
        // this.sidebarListCollectionView = setSidebarListCollectionView('TagSidebarListCollectionView', this.collection, this.tagCollection);
        // Approach #3
        // this.sidebarListCollectionView = setSidebarListCollectionView('TagSidebarListCollectionView');
    } else {
        // Approach #1
        setSidebarListCollectionView('cards');
        // Approach #2
        // this.sidebarListCollectionView = setSidebarListCollectionView('CardSidebarListCollectionView', this.collection, this.tagCollection);
        // Approach #3
        // this.sidebarListCollectionView = setSidebarListCollectionView('CardSidebarListCollectionView');
    }

    // render the list of content title links.
    this.$el.find('#content-manager-list-content').append(this.sidebarListCollectionView.render().el);
},
\$\endgroup\$
  • \$\begingroup\$ Welcome to Code Review. I'm sorry but this is not the site to ask about new functionality. We are reviewing working code, once you have code that do what you want it to do, re-edit or ask your question so we can suggest corrections/better way to do things. \$\endgroup\$ – Marc-Andre May 7 '15 at 20:25
  • 1
    \$\begingroup\$ Hi Marc-Andre, The code does do what I want it to do, as I explained above. It works. However, I am looking for ways to improve it, and I showed some of the alternative approaches I tried. But I am open to suggestions! I imagine on Stack Overflow this kind of question would be deemed inappropriate as there is no problem to solve, only improvements to be made. What do you think? \$\endgroup\$ – Lemmy May 7 '15 at 20:39
  • \$\begingroup\$ Well since it is working code I retracted my close-vote. I don't know if it's a good fit for Code Review or Stack Overflow, I let the community decide. \$\endgroup\$ – Marc-Andre May 7 '15 at 20:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.