【问题标题】:AngularJS doesn't work in MVC Partial ViewsAngularJS 在 MVC 部分视图中不起作用
【发布时间】:2015-01-21 04:22:55
【问题描述】:

我目前正在开发一个 ASP.NET MVC 项目。 Web 应用程序的站点是使用 Bootstrap 创建的。后来我添加了一些 AngularJS 脚本,以便能够将页面翻译成不同的语言。这适用于所有页面,但如果从页面加载部分视图则不是这样。 因此,例如,我有一个页面可以按名称或主机名搜索推出对象。在页面上,花括号中的所有角度表达式都被正确评估,并通过使用翻译脚本替换为多种语言的字符串。现在,如果我通过三个属性之一过滤对象,则会加载该页面的部分视图,显示搜索结果,但这里是未评估的角度表达式,它只显示表达式本身。

这是正常工作的页面:

@{
    ViewBag.Title = "{{ 'ROLLOUT-OBJECT_MANAGEMENT.TITLE' | translate }}";
}

<!-- html -->
<div style="font-size: 20px; margin-top: 20px;  margin-bottom: 20px;">
    <div class="gray-background list-group-item" translate="{{'ROLLOUT-OBJECT_MANAGEMENT.TITLE'}}"></div>
</div>
<div class="list-group">

    <div class="gray-background list-group-item">
        <div class="row margin-bottom">
            <div class="col-md-3">
                <h6 translate="{{'ROLLOUT-OBJECT_MANAGEMENT.FIRST_NAME'}}"></h6>
            </div>
            <div class="col-md-3">
                <h6 translate="{{'ROLLOUT-OBJECT_MANAGEMENT.SURNAME'}}"></h6>
            </div>
            <div class="col-md-3">
                <h6 translate="{{'ROLLOUT-OBJECT_MANAGEMENT.HOST_NAME'}}"></h6>
            </div>
        </div>
        <div class="row margin-bottom">
            <div class="col-md-3">
                <!-- referenced in getPartial() -->
                <input type="text" class="form-control" id="iFirstName" name="iFirstName" placeholder="">
            </div>
            <div class="col-md-3">
                <!-- referenced in getPartial() -->
                <input type="text" class="form-control" id="iSurName" name="iSurName" placeholder="">
            </div>
            <div class="col-md-3">
                <!-- referenced in getPartial() -->
                <input type="text" class="form-control" id="iHostName" name="iHostName" placeholder="">
            </div>
            <div class="col-md-3">
                <!-- getPartial() added to click through javascript-->
                <button type="submit" class="btn btn-primary btn-block" id="iButton"><span translate="{{'ROLLOUT-OBJECT_MANAGEMENT.BUTTON_SEARCH'}}"></span><span class="white-color glyphicon glyphicon-search"></span></button>
            </div>
        </div>
    </div>
</div>
<div class="list-group">
    <div class="gray-background list-group-item">
        <h5><span translate="{{'ROLLOUT-OBJECT_MANAGEMENT.RESULTS'}}"></span><span class="purple-color glyphicon glyphicon-globe"></span></h5>
    </div>
    <!-- referenced in getPartial() -->
    <div class="gray-background list-group-item">

        <div class="row">
            <div class="col-md-12" id="partialViewContainer">
                @{Html.RenderPartial("_RolloutObjectManagementResultsPartial");}
            </div>
        </div>
    </div>
</div>


<!-- layout -->
@Styles.Render(
  "~/content/chosen/chosen.css",
  "~/content/chosen/prism.css",
  "~/content/chosen/style.css",
  "~/content/bootstrap.css",
  "~/content/Site.css")

<!-- javascript -->
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/chosen/chosen.jquery.js"></script>
<script src="~/Scripts/chosen/prism.js"></script>
<script src="~/Scripts/jquery.unobtrusive-ajax.js"></script>
<script>
    var config = {
        '.chosen-select': {},
        '.chosen-select-deselect': { allow_single_deselect: true },
        '.chosen-select-no-single': { disable_search_threshold: 10 },
        '.chosen-select-no-results': { no_results_text: 'Oops, nothing found!' },
        '.chosen-select-width': { width: "95%" }
    }
    for (var selector in config) {
        $(selector).chosen(config[selector]);
    }
</script>
<script>
    //add functionality to button
    $('#iButton').click(function () {
        getPartial('0');
    });
</script>
<script>
    function previous() {
        var temp = document.getElementById("hPage").value;
        //alert(temp);//debug
        if (temp > 0) {
            temp = --temp;
        }
        getPartial(temp);
    }
    function next() {
        var temp = document.getElementById("hPage").value;
        //alert(temp);//debug
        temp = ++temp;
        getPartial(temp);
    }
</script>
<script>
    function getPartial(newPage) {
        //get search values
        var tempFirst = document.getElementById("iFirstName");
        var tempSur = document.getElementById("iSurName");
        var tempHost = document.getElementById("iHostName");
        var firstResult = tempFirst.value;
        var surResult = tempSur.value;
        var hostResult = tempHost.value;
        //ajax call
        $.ajax({
            url: "_RolloutObjectManagementResultsPartial",
            type: "POST",
            data: { firstName: firstResult, surName: surResult, hostName: hostResult, page: newPage, count: 10 },
            dataType: "html",
            error: function (xhr) {
                //alert(xhr.responseText);//debug
            },
            success: function (result) {
                $("#partialViewContainer").html(result).find("select").each(function () {
                    $(this).chosen({});
                })
            },
            complete: function () {
                //alert("everything worked");//debug
            }
        });
    }
</script>

这是它不起作用的部分视图(重要的是 {{...}} 中的表达式:

<!-- Import needed namespaces -->
@using RolloutTool.BusinessLayer.Foundation
@using RolloutTool.Utility

<!-- Initializing needed variables -->
@{
    List<RolloutObject> RolloutObjects = ViewContext.Controller.ViewBag.RolloutObjects;
    List<Cluster> Clusters = ViewContext.Controller.ViewBag.Clusters;
    string name = "";
    int count = 0;
    string rowID = "";
    int page = 0;
    if (ViewContext.Controller.ViewBag.Page != null)
    {
        page = ViewContext.Controller.ViewBag.Page;
    } 
}

<!-- html elements -->
<div class="row">
    <div class="col-md-12">
        <table class="table">
            <thead>
                <tr>
                    <th style="width:25%"><h6 translate="{{'ROLLOUT-OBJECT_MANAGEMENT.EMPLOYEE'}}"></h6></th>
                    <th style="width:20%"><h6 translate="{{'ROLLOUT-OBJECT_MANAGEMENT.WORK_STATION'}}"></h6></th>
                    <th class="text-center" style="width:15%"><h6 translate="{{'ROLLOUT-OBJECT_MANAGEMENT.EDIT'}}"></h6></th>
                    <th class="text-center" style="width:25%"><h6 translate="{{'ROLLOUT-OBJECT_MANAGEMENT.CLUSTER'}}"></h6></th>
                    <th class="text-center" style="width:15%"><h6 translate="{{'ROLLOUT-OBJECT_MANAGEMENT.ASSIGN'}}"></h6></th>
                </tr>
            </thead>
            <tbody>
                <!-- creating all RolloutObject Table rows -->
                @foreach (RolloutObject ro in RolloutObjects)
                {
                        <!-- generating rowID -->
                    rowID = "row" + Convert.ToString(count);
                    count++;
                        <!-- generating the full employee name -->
                    name = Functions.TryGetValue(ro.Employee.FirstName) + " " + Functions.TryGetValue(ro.Employee.SecondName) + " " + Functions.TryGetValue(ro.Employee.Name);
                    <tr id="@rowID">
                        <td>@name</td>
                        <td id="@Convert.ToString(rowID + "_hn")">@Convert.ToString(Functions.TryGetValue(ro.Hostname))</td>
                        <!-- generate link to right rolloutobjectedit -->
                        <td class="text-center"><a href="#"><span class="btn-pencil glyphicon glyphicon-pencil blue-color glyph-hov" onclick="location.href='@Url.Action("RolloutObjectEdit", "RolloutObject", new {hostName = ro.Hostname })'"></span></a></td>
                        <!-- generating the link for cluster addition and populating cluster dropdown -->
                        <td class="text-center">
                            <div class="row">
                                <div class="col-sm-12">
                                    <select class="chosen-select no-margin" style="width:100%" id="@Convert.ToString(rowID + "_cl")" name="iCluster" data-placeholder="Cluster">
                                        @if (ro.Cluster != null)
                                        {
                                            <option selected>@Convert.ToString(Functions.TryGetValue(ro.Cluster.Name))</option>
                                        }
                                        else
                                        {
                                            <option></option>
                                        }
                                        @foreach (Cluster cluster in Clusters)
                                        {
                                            <option>@Convert.ToString(Functions.TryGetValue(cluster.Name))</option>
                                        }
                                    </select>
                                </div>
                            </div>
                        </td>
                        <td class="text-center"><span class="btn-ok glyphicon glyphicon-ok green-color glyph-hov" onclick="callAjax('@rowID')" /></td>
                    </tr>
                }
            </tbody>
        </table>
    </div>
</div>

<div class="row">
    <div class="col-md-12">
        <input class="hidden" id="hPage" value="@Convert.ToString(page)" />
        <nav>
            <ul class="pager">
                <li class="pull-left"><a class="btn-paging glyphicon glyphicon-arrow-left" onclick="previous()"></a></li>
                <li class="pull-right"><a class="btn-paging glyphicon glyphicon-arrow-right" onclick="next()"></a></li>
            </ul>
        </nav>
    </div>
</div>

<!-- javascript -->
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/chosen/chosen.jquery.js"></script>
<script src="~/Scripts/chosen/prism.js"></script>
<script>
    function callAjax(idRow) {
        //get row values
        var tempTD = document.getElementById(idRow + "_hn");
        var tempSelect = document.getElementById(idRow + "_cl");

        var tempHostName = tempTD.textContent;
        var tempCluster = tempSelect.options[tempSelect.selectedIndex].text;

        //ajax call
        $.ajax({
            url: "AddToCluster",
            type: "POST",
            data: { clusterName: tempCluster, hostName: tempHostName },
            dataType: "html",
            error: function (xhr) {
                alert(xhr.responseText);
            },
            success: function (result) {
               
            },
            complete: function () {
                //alert("everything worked");//debug
            }
        });
    }
</script>
<script>
    function previous() {
        var temp = document.getElementById("hPage").value;
        //alert(temp);//debug
        if (temp > 0) {
            temp = --temp;
        }
        getPartial(temp);
    }
    function next() {
        var temp = document.getElementById("hPage").value;
        //alert(temp);//debug
        temp = ++temp;
        getPartial(temp);
    }
</script>
<script>
    function getPartial(newPage) {
        //get search values
        var tempFirst = document.getElementById("iFirstName");
        var tempSur = document.getElementById("iSurName");
        var tempHost = document.getElementById("iHostName");
        var firstResult = tempFirst.value;
        var surResult = tempSur.value;
        var hostResult = tempHost.value;
        //ajax call
        $.ajax({
            url: "_RolloutObjectManagementResultsPartial",
            type: "POST",
            data: { firstName: firstResult, surName: surResult, hostName: hostResult, page: newPage, count: 10 },
            dataType: "html",
            error: function (xhr) {
                alert(xhr.responseText);
            },
            success: function (result) {
                $("#partialViewContainer").html(result).find("select").each(function () {
                    $(this).chosen({});
                })
            },
            complete: function () {
                //alert("everything worked");//debug
            }
        });
    }
</script>

这是包含和加载脚本的 _Layout.cshtml:

<!DOCTYPE html>
<html ng-app="myApp">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewBag.Title - {{ 'TITLE.PROGRAM' | translate }}</title>
    @Styles.Render(
    "~/Content/css",
    "~/Content/flag-icon-css-master/assets/docs.css",
    "~/Content/flag-icon-css-master/css/flag-icon.min.css",
    "~/Content/Site.css")
    <script src="~/Scripts/angular/angular.js"></script>
    <script src="~/Scripts/angular/angular-translate.js"></script>
    <script src="~/Scripts/angular/angular-cookies.min.js"></script>
    <script src="~/Scripts/angular/translate.js"></script>
    <script src="~/Scripts/angular/angular-route.min.js"></script>
    <script src="~/Scripts/angular/angular-translate-storage-cookie.min.js"></script>
    <script src="~/Scripts/angular/angular-translate-storage-local.min.js"></script>    
</head>

<body ng-controller="Ctrl">
  
  <!-- Here is the html for the navigation bar etc. -->
  
    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/bootstrap")
    @RenderSection("scripts", required: false)
</body>
</html>

我真的不是 AngularJS 专家,因为我只想提供一些很酷的翻译功能,但我希望你们知道为什么它在部分视图中不起作用。

【问题讨论】:

  • 您需要在注册到 RenderPartial 视图和 ng-controller 的视图顶部添加脚本代码
  • 所以从它的样子看,您正在使用 JavaScript AJAX 调用将 DOM 元素替换为 HTML 部分,其中恰好包含 Angular 表达式。 Angular 不会正确渲染表达式,因为表达式是在 $compile() 阶段评估的,它创建了一个模板来链接到 scope。这通常发生在引导阶段,或指令中的特殊函数。
  • Angular.js 尽可能不鼓励直接的 DOM 操作,老实说,如果你在 Angular 中执行整个过程,你试图实现的逻辑看起来会更容易和更清晰。话虽这么说,我正在研究更多,很快就会发布一个可行的解决方案。
  • 在对该主题进行了一些研究并寻找解决方案之后,我只能说您似乎需要重构您的应用程序。考虑使用 Angular 的 $http 服务来填充您可以评估的变量,而不是使用 $.ajax 来替换 DOM 块。你现在构建 DOM 的方式不适用于 Angular。

标签: asp.net-mvc angularjs html twitter-bootstrap asp.net-mvc-partialview


【解决方案1】:

只是需要使用 ng-include("'controller/action'") 调用局部视图。 Apostrophe(') 在写 url 时很重要。

例子

 <div id="TestDiv" ng-include="templateUrl"></div>

在角度控制器内部

 var app = angular.module("Layout", []);
    app.controller("LoadPage", function ($scope, $http, $sce) {

   //Initially
    $scope.templateUrl = '/Home/DefaultPage';

    // To dynamically change the URL.
    $scope.NewProjFn = function () {
        $scope.templateUrl = '/Home/ProjectPage';
    };
});

重新实现它可能一点也不难,但是通过使用 ng-include,您也不需要进行 ajax 调用。它自己完成这一切,包括 ajax 调用、编译和显示。但是像 ng-click 和其他事件这样的函数不能作为一次性编译过程来工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-08
    • 1970-01-01
    • 2015-03-03
    • 1970-01-01
    • 2014-09-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多