Dynamically assign controllers using ng-controller

My goal is to utilize the bootstrap.ui tabset feature with an array of tab settings. These settings include the name of the controller responsible for handling its contents in order to keep my 'tab-control' template clean and simple.

<div tabset>
    <div ng-repeat="tab in tabs"
         tab
         active="tab.isActive">
        <span tab-heading>{{ tab.title }}</span>
        <span ng-inlcude="tab.templateUrl" ng-controller="tab.controller"></span>
    </div>
</div>

(please note that I have not yet implemented the ng-include attribute in my code, as I was first experimenting with ng-controller.)

Initially, I attempted to use the controller's name directly... however, ng-controller did not accept this and did not function as expected.

Next, I tried translating the name to a controller using the following snippet.

for (var tabIdx = 0; tabIdx < tabs.length; tabIdx++) {
    var tab = tabs[tabIdx];

    if (typeof tab.controllerName == 'string') {
        var childScope = tab.scope = tab.scope || $scope.$new();

        childScope.someValue = 'I am created as [' + tab.controllerName + '] requested.';

        tab.controller = $controller(tab.controllerName, { $scope: childScope });
    }
}

However, Angular alerted me that it expected a function but received a controller instead (you would think that ng-controller wouldn't mind receiving a controller).

So, I adjusted the $controller call to:

tab.controller = $controller(tab.contollerName, { $scope: childScope }).constructor;

While this solution somewhat worked, the scope was not ideal.

As a next step, I considered providing another function to the ng-controller:

tab.controller = $controller.bind(null, tab.contollerName, { $scope: childScope });

However, the ng-controller could not locate the $injectables in this scenario.

Is there a way to make this configuration functional?

Answer №1

To dynamically assign the controller, I recommend creating a directive for this purpose.

app.directive('tabCtrl', function ($controller) {
  return {
    restrict: 'A',
    controller: function ($scope, $element, $attrs) {
      return $controller($scope.tab.controller, {
        $scope:   $scope,
        $element: $element,
        $attrs:   $attrs
      });
    }
  };
}); 

<span ng-inlcude="tab.templateUrl" tab-controller="tab.controller"></span>

Check out jsbin for more insights


If you want to enhance this further, consider implementing the following approach:

app.directive('tab', function ($controller) {
  return {
    restrict: 'E',
    template: '<ng-include src="tab.template"></ng-include>',
    controller: function ($scope, $element, $attrs) {
      return $controller($scope.tab.controller, {
        $scope:   $scope,
        $element: $element,
        $attrs:   $attrs
      });
    }
  };
}); 

Extended version available on jsBin

Answer №2

To specify which controller to use in the template, you can simply define it as shown below:

Controller:

app.controller('mainController', function($scope) {
  $scope.modules = [
    { id: 1, name: 'module1', template: 'template1.html' },
    { id: 2, name: 'module2', template: 'template2.html' }
  ]
});

HTML:

<div ng-repeat="module in modules track by module.id">
    <label class="module">{{module.name}}</label>
    <div ng-include="module.template"></div>
 </div>

and in the template:

<div ng-controller="ctrl2">
  ...
</div>

Here is a sample plunker for reference: http://plnkr.co/edit/AbCdEfGhIjKlMnOpQrSt?p=preview

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

Clicking on a button in the Shield UI Grid Toolbar will apply filters to

Currently, I am working with a grid that utilizes a template for the toolbar. In this grid, there is a column labeled "Status." My goal is to filter the rows so that only those where the Status equals Request to Reschedule, Cancelled, Office Call Required, ...

How can AngularJS be used to enforce a numeric format (including digits and decimal points) in a textfield?

I am in need of a directive to format this specific input For example, 423.33 is considered a valid number while 423.333 is invalid. Only positive numbers including 0 are allowed. However, the user should not be able to enter 0423.33 If only a number wit ...

When using CasperJS to capture multiple screenshots, the most recent screenshot will replace all previous ones

Exploring CasperJS has been a great experience for me. Despite my enjoyment, I've encountered an issue with casper.capture() that has me stumped. I've set it up to capture screenshots whenever a test fails and placed it in a separate setup module ...

Utilizing SCSS to implement custom animations according to specific element IDs

How can I add different animations based on the ID of two DIVs with the same class when clicked? JSX: <div className="card"> <div id="front" className={frontClasses.join(' ')} onClick={clickedFront}> OPEN ...

Collapse the mobile nav bar upon clicking an item

I'm currently facing a challenge with the navigation bar on my event landing page. The issue is that when I open the navbar in mobile view, it does not collapse back after clicking on an item. Instead, it remains open and covers almost 3/4 of the scre ...

Can you please guide me on how I can implement a top AJAX menu like the one on StackOverflow

Have you seen the menu that appears when you first visit a website, with an 'x' on the right to close it? I believe this is done through AJAX - what specific terms should I look up to implement this feature? ...

Retrieve the rightmost selected input from each row by using only one jQuery(Sizzle) selector

This scenario is quite intriguing, and I stumbled upon it in my project today. We have a table of checkboxes, with one type being hierarchical - meaning if one is checked, all preceding checkboxes of the same type magically get checked as well. The challe ...

Error: The function $scope.apply is invalid and cannot be executed

I am attempting to display the contacts list after retrieving it using rdflib.js. The data is being loaded and stored in the list within the scope. However, I am running into an issue where the $scope is not updating, and it appears that I may be calling ...

Struggling with updating information in AngularJS

Developing a web application using the MVC framework with AngularJS has been an interesting journey for me. Here is a snippet of my application: var app = angular.module("AngularApp", []); One key component of my application is the controller: app.cont ...

Issue with npm during installation of REACT - not functioning as expected

After executing all the necessary commands on the command line, including globally installing npm with npm install -g create-react-app, as well as running npx create-react-app <myprojectname> and clearing the npm cache, I consistently encountered an ...

What could be the reason behind the error message "module not available" appearing in JSFiddle

I have officially established this module: angular.module('dashboard', []) .controller('dashboardController', ['$scope', function ($scope) { $scope.data = "555"; }]); Here is the ...

Utilizing NGRX to inject reducer state into components

In my current setup, I have a tasks reducer that holds the following structure: { error: false,     loading: false,     tasks: [] } Now, this object is being passed down to a simple component like this: <task-list tasks="tasks$ | async"> ...

What sets {props.children} apart from conventional objects?

Currently, I am deep diving into React by taking a crash course. The topic at hand is nested components and props, which has left me slightly confused. In my attempt to create a simple comment section, similar to thishttps://i.sstatic.net/7uNlj.png ...

Redirect data from a server's database to a local environment for testing purposes

I have been given a project at a company where I need to make some enhancements and modifications as a side project. Currently, I have an almost finished website with around 13,000 lines of code in C# and JavaScript. To avoid any mishaps on the live websit ...

What is the best way to clear the content of a contenteditable element in React?

I have a scenario where I am rendering an array of items, each with a contenteditable field. MainComponent.js import { useState } from "react"; import Item from "./Item"; import "./styles.css"; export default function MainC ...

Why am I unable to utilize methods in Vue.js?

Hey everyone, I'm currently working on a website that includes a home page and a specific 'Brazil' component. To switch between the two, I am using vue router. Within the Brazil component, there is a calculator feature that should take a gra ...

Problems encountered with nested AJAX calls and the $.when.apply function handling deferred promises efficiently

I am attempting to create a triple nested series of AJAX calls, as shown in the basic structure below (fail calls have been omitted). Progress is being made up to the second level with the eventCalls. The final when.apply.done only triggers after every si ...

In Chrome, the `Jquery $('input[name=""]').change(function will not be triggered unless there is an unhandled error following it

Here is a script that I've created to make certain inputs dependent on the selection of a radio button. The 'parent' input in this case is determined by the radio button choice. Upon document load, the script initially hides parent divs of ...

Retrieving the value of a JSON object within a nested response

I need to extract specific values from a JSON response related to cars. Specifically, I want to retrieve the values for car, car.Make, and car.Price. However, my current method does not seem to be working. Here's what I've tried: $.each(jqXHR. ...

What is the best way to modify the class of my <li> element with JavaScript?

My asp.net project utilizes a master page that includes a list within it. <ul id="navigation"> <li id="li1" runat="server" class="selected"><a href="Events.aspx">Events</a></li> <li id="li2" runat="server ...