Alter the subview in real-time

When using EmberJs, I need to develop a view that can hold different types of players (such as Youtube, Photosynth, Html Content, etc.) and it should change dynamically based on a controller property that specifies the item to play.

I've already created several views for each type of player, like in the example below:


App.basePlayer = Em.View.extend({
    templateName : 'base'
  });

App.playerEmpty= App.basePlayer.extend({
    templateName : 'empty'
  });

App.player1= App.basePlayer.extend({
    templateName : 'p1'
  });

App.player2= App.basePlayer.extend({
    templateName : 'p2'
});

Now, I need to create a view that can append one of these player views in its content. If the view is a normal Ember.View that binds a view stored in a property, it works when initialized, but won't re-render if a new view is set.

To address this issue, I came up with a ContainerView that holds the player:


App.IndexView = Em.CollectionView.extend({

  childViews: ['header', App.playerEmpty],

  header: Em.View.extend({
    templateName : 'h'
  })

});

I also created two methods that update the player view when the Item property in the controller changes:


onItemChange : function(){
    var item = this.get('controller.item'),
        playerClass = null;

    if(item === null){
      playerClass = App.playerEmpty;
    }
    else if(item instanceof App.Item1){  
      playerClass = App.player1;
    }
    else if(item instanceof App.Item2){  
      playerClass = App.player2;
    }

    this.setPlayerView(playerClass);
}.observes('controller.item'),

setPlayerView: function(playerClass){
    var v =this.get('childViews').find(function(item, index, enumerable){
      return item instanceof App.basePlayer;
    });

    this.get('childViews').removeObject(v);

    this.get('childViews').pushObject(playerClass.create());
}

Is this solution optimal or is there a better approach?

You can see an example here:

Answer №1

When writing code in Ember.js, it is best practice to ensure that your views are dependent on properties in your models. Thanks to Embers' powerful binding abilities, any changes in the models will automatically reflect in the views.

In this scenario, I have created a single player view that determines its template based on the item data. By doing this, you only require one player view and eliminate the need for observer code in the collection view:

App = Ember.Application.create();

App.player = Em.View.extend({
  templateName : function() {
  item = this.get('content');
    if(item === null){
      return 'empty';
    }
    else if(item instanceof App.Item1){  
      return 'p1';
    }
    else if(item instanceof App.Item2){  
      return 'p2';
    } else {
      return 'base';
    }
  }.property('content')
});

App.IndexView = Em.CollectionView.extend({

  childViews: ['header', App.player],

  header: Em.View.extend({
    templateName : 'h'
  })

});

App.Router.map(function() {
  // define your routes here
});

App.IndexRoute = Ember.Route.extend();

App.Item1 = Em.Object.extend({
  type : 1
});

App.Item2 = Em.Object.extend({
  type : 2
});

App.IndexController = Ember.Controller.extend({
  item: null,

  actions : {
    setItem : function(idx){
      switch(idx){
        case 0:
            this.set('item', null);
          break;
        case 1:
            this.set('item', App.Item1.create());
          break;
        case 2:
            this.set('item', App.Item2.create());
          break;
      }
    }
  }
});

This approach offers a simple solution. If your different player views require more complex behaviors and truly demand distinct view classes, consider exploring programmatic creation of child views, but try to avoid using observers.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Enhance data table by displaying a set number of rows that do not completely fill the table's height

I'm currently attempting to implement a v-data-table with fixed header and footer. However, I've encountered an issue where if I set the table height to be larger than the row height, the table takes on the defined height and the footer ends up b ...

generate a series of nested divs within one another

I am looking to create a custom nested loop that will generate div elements based on the content of my h1 and h2/h3 tags. I understand this may have been covered in other inquiries, so any guidance would be appreciated :) Here is the initial HTML: <h1& ...

Unexpected box-shadow issue with Material UI's Box component

During the development of my application, I encountered an issue with rendering a list of items. The state consists of a simple array containing elements with a name, an identifier, and a selected key that determines whether special styles should be applie ...

What would be an effective method for sending a multitude of parameters to a controller?

I am currently working on an application that utilizes Java with the Spring framework and Javascript with AngularJs framework. The application features a table displaying a list of objects along with two text fields for filtering these objects. The filteri ...

Troubleshooting Axios Error while Sending Data in MERN Stack Application

In my development setup, I'm testing model validation specifically for the length of a name variable. The front-end is configured at http://localhost:3000/ using React + axios, while the back-end utilizes express + node. To enable communication betwe ...

Setting up RTL (Right to Left) functionality in Material UI version 5 - A Step-by-Step Guide

After updating my app to version 5 of Material-UI from version 4, I noticed that the RTL support is no longer functioning. I carefully followed the instructions in the documentation: https://mui.com/guides/right-to-left/ The current outcome is that the ...

Struggling to establish a functioning proxy in my React and Node application

In the process of developing a react client app with a node.js express backend, I have encountered an issue related to project structure. https://i.sstatic.net/8rID0.png The client app includes a proxy configuration in its package.json file: "proxy": "h ...

Troubleshooting a jQuery issue involving socket.io

I recently created a chat room using socket.io and jQuery. Inexperienced with node.js, I uploaded the files to an old FTP to get it online. Upon loading the website, I encountered an error in the console: Uncaught ReferenceError: io is not defined at ...

Most effective method for waiting for a dropdown to load and choosing a value using Selenium in JavaScript

My current task involves interacting with a website built in React using Selenium to choose a value from a dropdown menu. Given that the website is built in React, I understand that waiting for the DOM to be ready may not always work as expected, but I st ...

Choosing a particular 2D array based on another variable in jQuery and JavaScript

Within my project, I am utilizing 2D arrays to append specific divs under particular circumstances. In an effort to streamline and enhance the code, I attempted to create a variable that would determine which array to utilize based on the id of an HTML < ...

What is the best way to extract an object from an array that only includes one element, and that element is an object?

Here is the output of my updated function: db.collection('SOCIAL').get().then((snapshot) =>{ snapshot.docs.forEach(doc => { tempData.push(doc.data()) }) return tempData }) I want to store these valu ...

Prevent altering client values via developer tools

Our application is built using HTML5, the Foundation framework by ZURB, and AngularJS. We are seeking a way to prevent users from accessing and changing the values of our Angular objects (specifically scope variables) through the developer tool console. ...

"Encountering an error with ExpressJS where it cannot GET a file, preventing access to other folders' content

My goal is to set up a simple server using expressJS to retrieve data for my Angular application. However, I've encountered an error that says 'Cannot GET/'. This is the code snippet of the webserver I attempted to create: var express = re ...

Leveraging web workers for asynchronous API calls

Trying to find an efficient method for utilizing web workers to handle api calls, my current approach involves the following on the client side: - worker-client.js export const workerFetch = (method = "get", url = "/", data = {}) => new Promise((res ...

Is it possible to trigger a click event exclusively on a parent element?

One feature I'm trying to implement in my app is the ability to click on an item, such as changing the background color or text, and have a modal pop up with a color picker to customize the color of that specific item. However, I've run into an i ...

Tips for locating a value that differs from an item in a v-autocomplete box

I am using a v-autocomplete component: <v-autocomplete v-model="fromPrice" :items="listOfFromItems" dense solo label="from" hide-detail ...

Using Javascript to Retrieve Object-Related Information from an Associative Array

I have a list of students' names along with the grades they achieved for the semester. How can I modify my JavaScript code to display the first names of students who earned an "A" grade based on the array provided? This is my current progress, but I k ...

Tips for effectively showcasing the counter outcome amidst the increase and decrease buttons

Currently, I am in the process of learning Angular and have created a component called quantity-component. Within the quantity-component.component.html file, I have implemented 2 buttons for increment (denoted by +) and decrement (denoted by -). The decrem ...

Ways to maintain group settings for a Telerik MVC Grid connected to Ajax

Currently, I am seeking guidance on how to persist grouping settings on an Ajax bound Telerik ASP .NET MVC grid. My goal is to have the grid display revert back to its previous settings when a user navigates away to a detail screen and then returns to the ...

Reading values from a properties file using HTML

Here's a snippet of my HTML code: First name: <input type = "text" > Last name: <input type = "text"> Instead of manually inputting the field values (First name, Last name) in the HTML, I am interested in reading them ...