Utilizing the controller specified in the template that has been included

Within this snippet of code, I am attempting to utilize a controller named FooCtrl that is defined in the included template app/foo.html, using the directive common.script.

angular.module('common.script', []).directive('script', function() {
  return {
    restrict: 'E',
    scope: false,
    compile: function(element, attributes) {
      if (attributes.script === 'lazy') {
        var code = element.text()
        new Function(code)()
      }
    }
  }
})
angular.module('app.templates', ['app/foo.html'])
angular.module("app/foo.html", []).run(function($templateCache) {
  $templateCache.put("app/foo.html",
    "<script data-script=\"lazy\">\n" +
    "   console.log('Before FooCtrl')\n" +
    "angular.module('app').controller('FooCtrl', function($scope) {\n" +
    "console.log('FooCtrl')\n" +
    "})\n" +
    "<\/script>\n" +
    "<div data-ng-controller=\"FooCtrl\">app\/foo.html\n" +
    "<\/div>"
  )
})
angular.module('app', ['common.script', 'app.templates']).controller('ApplicationCtrl', function($scope) {
  console.log('ApplicationCtrl')
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular.min.js"></script>
<div data-ng-app="app" data-ng-controller="ApplicationCtrl">
  <div data-ng-include="'app/foo.html'"></div>
</div>

Despite my expectations of seeing FooCtrl in the console output, AngularJS throws an error:

Error: [ng:areq] Argument 'FooCtrl' is not a function [...]

I am puzzled as to why this error occurs! The template's code is executed before the exception is raised, indicating that the controller should be defined. How can I rectify this issue?

Answer №1

The main issue at hand is the lazy loading of resources, which presents a challenge in this scenario! There exists an abundance of materials and related discussions on this particular subject.

An effective solution could involve an enhanced common.script directive:

'use strict'

angular.module('common.script', [])

.config(function($animateProvider, $controllerProvider, $compileProvider, $filterProvider, $provide) {
  angular.module('common.script').lazy = {
    $animateProvider: $animateProvider,
    $controllerProvider: $controllerProvider,
    $compileProvider: $compileProvider,
    $filterProvider: $filterProvider,
    $provide: $provide
  }
})

.directive('script', function() {
  return {
    restrict: 'E',
    scope: {
      modules: '=script'
    },
    link: function(scope, element) {
      var offsets = {}, code = element.text()

      function cache(module) {
        offsets[module] = angular.module(module)._invokeQueue.length
      }

      function run(offset, queue) {
        var i, n
        for (i = offset, n = queue.length; i < n; i++) {
          var args = queue[i], provider = angular.module('common.script').lazy[args[0]]

          provider[args[1]].apply(provider, args[2])
        }
      }

      if (angular.isString(scope.modules)) {
        cache(scope.modules)
      } else if (angular.isArray(scope.modules)) {
        scope.modules.forEach(function(module) {
          cache(module)
        })
      }

      /*jshint -W054 */
      new Function(code)()

      Object.keys(offsets).forEach(function(module) {
        if (angular.module(module)._invokeQueue.length > offsets[module]) {
          run(offsets[module], angular.module(module)._invokeQueue)
        }
      })
    }
  }
})

The only drawback to consider with this approach is that you must specify the module(s) you wish to extend within a script tag:

<script data-script="'app'">
  angular.module('app').controller('FooCtrl', function($scope) {
    console.log('Success!')
  })
</script>

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

How can you set a $_GET variable without having to reload the page?

I have a table on my website that displays values for each row, and here's an example code snippet: //JAVASCRIPT <tr onclick="window.history.replaceState(null, null, 'myPage.php?ID=2');"> The URL changes with this code, but it doesn& ...

Use Material UI TextField to prompt an email client or make a phone call

I am facing an issue with a MaterialUI TextField component. In certain situations, the TextField is disabled and I want it to be clickable as if it were an anchor tag leading to a phone number or email address. However, it seems that making the input behav ...

the function fails to run upon clicking the button again

Here is the current function in use: function beTruthful() { if (document.getElementById("about").style.opacity = "0") { document.getElementById("about").style.opacity = "1"; } else { document.getElementById("about").style.opacity ...

Making cross domain requests from AngularJS to an ExpressJS app hosted on Heroku

I have created a standalone ExpressJS API that is designed to serve mobile apps and web apps. I am currently testing the API by using a basic AngularJS client app that I developed. The API functions properly when hosted locally. However, I am encountering ...

Having issues with InstaFeed (search) feature and jQuery Mobile

As a new developer, I am working on my first JQM site. However, I am facing an issue with my search input form where the instafeed photos do not show up until after a manual page refresh following submission. Despite numerous attempts, I cannot seem to res ...

Tips for efficiently combining mergeMap observables and providing a singular value for the entire observable

Consider this particular case involving TypeScript/angular with rxjs 6.5: main(){ const items = ['session', 'user']; const source: Observable<any> = from(items); source .pipe( ...

Comparing Canvas and CSS3 for Website Development

Many discussions focus on comparing games with high levels of interaction, but my project involves a web application that manipulates objects individually. These objects can be images or text, and they can be replaced, resized, rotated, zoomed in, and dele ...

Transforming the header of a table in a CSV file into a schema field

My task is to create a schema for a CSV file using Mongoose, but upon inspecting the file, I discovered it contains nearly a hundred fields or columns. While I am familiar with defining schemas in Mongoose for files with only a few fields, I am unsure ho ...

Avoiding repetition in json array using reactjs with the help of axios

After receiving guidance from @Akrion, I managed to resolve the issue! Check out my comments below our conversation for the solution. I am relatively new to reactJS and axios, but I recently collaborated with a classmate on a project. Now, I find myself s ...

Issues with the script manager functionality in asp.net

I need to display a message to the user after submitting a form and include the ID received from the database in the message like this: int reqid = getIDFromDatabase(); string scrp = "<script>alert('Your request has been submitted successfully ...

Tips for checking the type radio button input with Angular.js

I want to implement validation for a radio button field using Angular.js. Below is the code snippet I am working with: <form name="myForm" enctype="multipart/form-data" novalidate> <div> <input type="radio" ng-model="new" value="true" ng- ...

What is the best way to manage a multi-select dropdown with checkboxes in Selenium Webdriver?

Below is a snapshot of the drop-down I am working with. In order to handle multiple selections, I currently have code that clicks on the arrow in the drop-down and then selects the corresponding checkbox. However, I would like a more efficient solution fo ...

Error encountered while attempting to save process using ajax - 500 Internal Server Error

I am facing an issue with my CodeIgniter code where I encounter a 500 internal server error when trying to save data. I am not sure why this problem is happening and would appreciate any help. Below is the AJAX code in the view: function save() { $(& ...

Troubleshooting the issue with generateStaticParams() in NextJs/TypeScript

My NextJs app has a products page that should render dynamic routes statically using generateStaticParams(). However, this functionality does not work as expected. When I run "npm run build," it only generates 3 static pages instead of the expected number. ...

Reload a tab on an ajax-enabled webpage

I am currently facing an issue with refreshing a tab instead of the entire page using Ajax. The specific tab in question involves deleting credit cards. When I select the credit card I want to delete and confirm, I use "window.location.reload();" to refres ...

Issues with loading NextJS videos can occur when accessing a page through a link, as the videos may fail to load without

Issue Greetings. The problem arises when attempting to load muse.ai videos on-page, specifically when accessing the page with a video embedded through a NextJS link. To showcase this issue, I have provided a minimal reproducible example on StackBlitz her ...

Angular and Express encountering a CORS 403 issue

My Express configuration includes settings that run on a different domain: app.use(function(req, res, next) { res.setHeader("Access-Control-Allow-Origin", 'http://localhost:3000'); res.setHeader("Access-Control-Allow-Credentials","true") ...

An error occurred while trying to upload the image: Undefined property 'subscribe' cannot be read

Recently, I implemented a create post function that allows users to fill in the title, content, and upload an image. However, I encountered an issue where the progress bar fills up and the image gets uploaded to Firebase successfully, but it doesn't a ...

Download the ultimate HTML package with a built-in chart.js component directly from your nuxt app

I have a task to create a compact Nuxt application that produces a basic HTML file containing informative sections about the services offered to the clients of my organization. The main purpose is to generate an HTML file that can be easily downloaded and ...

Using jQuery, you can create and add an element to the page when a user clicks

Currently, my webpage contains numerous anchor tags that link to various video files, along with a single div element: <a href="http://www.example.com/example-1.mkv" class="video">1</a> <a href="http://www.example.com/example-2.mkv" class=" ...