【问题标题】:AngularJS template loading late. Directive not able to find the elementsAngularJS 模板加载较晚。指令找不到元素
【发布时间】:2020-09-01 11:53:18
【问题描述】:

我正在为现代工具准备一个基于 .net 的 AngularJS Web 应用程序(摆脱 nuget 以支持 npm,与 webpack 捆绑等),然后将其重写为 Angular。

我遇到了捆绑版本的问题,其中指令试图将点击事件绑定到模板锚标记 () 但尚未加载模板。

在每个 JS 文件都有许多 标签的旧版本上,这不会发生。 指令在订单上是第一个,模板的控制器(在 ng-include 中加载并使用该指令)之后.

在捆绑版本中,我只是将 .js 文件更改为 .ts,添加了 npm 依赖项,每个文件和 webpack 条目中所需的导入语句,我保持与旧 index.html 中相同的顺序。尽管如此,当 de 指令代码运行时,它搜索的元素还不存在。

受影响的部分:(已更新 @bryan60 回答建议)

shell.html

...
<div data-ng-if="vm.showMenuBar" data-ng-include="'/app/layout/sidebar.html'" class="fader-animation"></div>
...

shell.ts

import angular from 'angular';

const sideBarTemplate = require('./sidebar.html')

let controllerId = "shell";
angular.module("eqc").controller(controllerId, ["$rootScope", "$templateCache", "$window", "authService", "common", "config", shell]);

function shell($rootScope, $templateCache, $window, authService, common, config) {

    $templateCache.put('app/layout/sidebar.html', sideBarTemplate)

sidebar.html

<div data-cc-sidebar data-ng-controller="sidebar as vm">
<div class="sidebar-filler"></div>
<div class="sidebar-dropdown"><a href="#">Menu</a></div>
<div class="sidebar-inner">
    <div class="sidebar-widget"></div>
    <ul class="navi">
        <li class="nlightblue fade-selection-animation" data-ng-class="vm.isCurrent(r)" data-ng-repeat="r in vm.navRoutes">
            <a href="{{r.url}}" data-ng-bind-html="r.config.settings.content"></a>
        </li>
    </ul>
</div>

cc-sidebar 指令:

app.directive('ccSidebar', function () {
    // Opens and clsoes the sidebar menu.
    // Usage:
    //  <div data-cc-sidebar>
    // Creates:
    //  <div data-cc-sidebar class="sidebar">
    var directive = {
        link: link,
        restrict: 'A'
    };
    return directive;

function link(scope, element, attrs) {
    var $sidebarInner = element.find('.sidebar-inner');
    var $dropdownElement = element.find('.sidebar-dropdown a');
    element.addClass('sidebar');
    $dropdownElement.click(dropdown); // <--- Here's the problem. 'dropdown' function is omitted but its defined in the next line
                                      // The error on the console is: TypeError: "$dropdownElement.click is not a function"
                                      // That's because it is never found

main.ts

import "./eqc";
import "./config"
import "./config.exceptionHandler"
import "./config.route"
//All folders bellow have index.ts in them including their .ts files
import "./common"
import "./services"
import "./Views"
import "./layout"

eqc.ts

import 'jquery';
import angular from 'angular';
import 'angular-animate';
import 'angular-route';
import 'angular-sanitize';
import 'angular-messages';
import 'angular-local-storage'
import 'angular-ui-bootstrap';
import 'angular-ui-mask';
import 'angular-loading-bar';
import 'breeze-client';
import 'breeze-client/breeze.bridge.angular';

let eqc = angular.module("eqc", [ .....

webpack.config.ts

const path = require('path');

module.exports = {
    mode: "development",
    entry: "./src/app/main.ts",
    output: {
        path: path.resolve(__dirname, "src/dist"),
        filename: "bundle.js"
    },
    module: {
        rules: [
            //All files with a '.ts' or '.tsx' extension will be handled by 'ts-loader'
            {
                test: /\.tsx?$/,
                use: { loader: "ts-loader" }
            },
            {
                test: /\.html$/,
                use: { loader: 'html-loader' }
            }
        ]
    },
    resolve: {
        //Add '.ts' and '.tsx' as a resovaable extension
        extensions: [".webpack.js", ".web.js", ".ts", ".tsx", ".js"]
    },
    devtool: "source-map"
};

我的文件夹结构:

【问题讨论】:

  • 你可能应该显示导致问题的指令配置和模板,而不是描述它......如果你已经正确地将你的模板文件包含在你的包中,ng-include 很好。所以你的模板代码和 webpack 配置在这里也很重要.. 虽然通常我建议使用模板缓存并要求你的模板并让 w​​ebpack 内联它们
  • 用我的代码更新了问题。
  • 具体的错误是什么,还有shell指令配置?我对您的代码有点困惑,因为您似乎使用 ng-include 作为模板,但模板也有一个指令?我不确定你为什么要这样配置或者指令如何链接到模板
  • 修复了缺失的代码部分。是的,在 sidebar.html 模板中使用了 cc-sidebar 指令,然后将其插入到 shell.html 上的 ng-include 中
  • 这是哪个 angularjs 版本?你为什么选择喜欢,使用各种断开连接的指令将这个指令拼凑在一起,而不是在指令声明中设置模板和控制器或使用组件?

标签: angularjs webpack bundling-and-minification


【解决方案1】:

由于缺少代码/细节,不确定您的问题到底是什么……但通常来说,使 ng-include 与 webpack 一起工作的最简单方法是使用 require 语句和模板缓存....

假设您有一些模板,例如:

<ng-include src="'app/my-included-template.html'"></ng-include>

在该模板的控制器中,您将设置类似...

const myIncludedTemplate = require('./my-included-template.html')

function MyController($templateCache) {
    $templateCache.put('app/my-included-template.html', myIncludedTemplate)
}

要使 require 语句与 webpack 一起工作,你需要配置 html 加载器,我在我的模块规则数组中这样做...

  {
    test: /\.html$/,
    use: [
      'html-loader'
    ],
  },

这个特定的实现需要你npm install --save-dev html-loader

这将指示 webpack 将您的模板内联到源文件中,然后您的控制器将立即将其放入模板缓存中,以便可以正确加载它而无需担心 webpack 包结构本身,因为 angular 会检查模板缓存在远程加载之前。这也是一种通常更高效的做事方式。

您也可以在定义指令/组件模板时做类似的事情:

template: require('./my-directive-template.html'),

这产生了与 webpack 相同的好处,只是内联模板,因此不需要远程加载。

【讨论】:

  • 嗨 brigan60,感谢您的回复。我用你的建议更新了我的代码,但仍然出现同样的错误。我已经根据您的建议使用代码更新了我的问题。希望现在更容易看到我做错了什么。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-11
  • 2013-10-28
  • 1970-01-01
  • 1970-01-01
  • 2014-09-02
相关资源
最近更新 更多