1

AngNoob在这里。我有一些全局导航,它使用 routeProvider 来换出视图内的外部 html 页面。在视图中,我设置了一个列表类型的子导航(使用 ng-repeat 创建),用于切换外部 html 文件中的 div。如果我在 appCtrl 中手动设置它,我可以让它加载页面:

//Here I set the initial value
    $scope.page = 'Comfort Homes of Athens';

但是当我单击具有 ng-click 的跨度时。我什么都得不到。我开始认为这是一个范围问题,但是当我只放一个 ng-click='alert()' 时,它也什么也没做。

我已经阅读了其他帖子,但大多数似乎都将 ng-click 放在 ng-switch 内部,而不是相反。并且在他们的示例中也没有使用路由。仍然是 Angular 的新手,所以也许我还没有遇到过。

应用程序 HTML:

<body ng-app="app">
<header ng-include="header.url" ng-controller="nav"></header>
<article ng-view></article>
<footer ng-include="footer.url" ng-controller="nav"></footer>
    <script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.16/angular.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.16/angular-route.js"></script>
    <script type="text/javascript" src="js/data.js"></script>
    <script type="text/javascript" src="js/model.js"></script>
</body>

外部 HTML 文件:

<div id="web" class="wrapper">
    <aside class="boxModel">
        <div id="controller" class="container">
            <div class="topBox bluebg subNavBar"><h1 class="white">Projects</h1></div>
            <div ng-controller="nav" id="controls" class="botBox whitebg">
                <span ng-repeat='item in webProjects' ng-click="page='{{item.name}}'">{{item.name}}</span>
            </div>
        </div>
    </aside><section ng-switch on="page" class="boxModel">

        <div ng-switch-when="Comfort Homes of Athens" id="sandbox" class="container round box whitebg">
           <h1>Here is link 1</h1>
        </div>

        <div ng-switch-when="Sealpak Incorporated" id="sandbox" class="container round box whitebg">
            <h1>here is Link 2</h1>
        </div>
    </section>
</div>

JS:

var app = angular.module("app", ["ngRoute"]);

function nav($scope) {
    $scope.templates = templates;
    $scope.header = $scope.templates[0];
    $scope.footer = $scope.templates[1];
    $scope.mainNav = mainNav;
    $scope.footNav = footNav;
}
app.config(function($routeProvider) {
    $routeProvider.when('/',{
        templateUrl: "templates/home.html",
        controller: "AppCtrl"
    }).when('/templates/web.html',{
        templateUrl: "templates/web.html",
        controller: "AppCtrl"
    }).when('/templates/seo.html',{
        templateUrl: "templates/seo.html",
        controller: "AppCtrl"
    }).otherwise({
        template: "This doesn't exist!"
    });
});

app.controller("AppCtrl", function($scope) {
    $scope.webProjects = webProjects;
    $scope.seoProjects = seoProjects;
//Here I set the initial value
    $scope.page = 'Comfort Homes of Athens';
});
4

3 回答 3

4

对你来说不幸的是,当你的where不是ng-repeat的子 范围,而是.ng-controller="nav"<section>ng-switchng-controller="nav"AppCtrl

您可以尝试ng-click="$parent.$parent.page=item.name"仅了解角度范围。

<div id="web" class="wrapper">
<aside class="boxModel">
    <div id="controller" class="container">
        <div class="topBox bluebg subNavBar"><h1 class="white">Projects</h1></div>
        <div ng-controller="nav" id="controls" class="botBox whitebg">
            <span ng-repeat='item in webProjects' ng-click="$parent.$parent.page=item.name">{{item.name}}</span>
        </div>
    </div>
</aside><section ng-switch on="page" class="boxModel">

    <div ng-switch-when="Comfort Homes of Athens" id="sandbox" class="container round box whitebg">
       <h1>Here is link 1</h1>
    </div>

    <div ng-switch-when="Sealpak Incorporated" id="sandbox" class="container round box whitebg">
        <h1>here is Link 2</h1>
    </div>
</section>

我不建议使用此解决方案,因为它非常难看。@link64 的解决方案更好,但我认为继承model是如此隐式并创建了紧密耦合的代码。在这里,我提出了另一种解决方案,我希望通过发出事件来更好:

<span ng-repeat='item in webProjects' ng-click="$emit('pageChange',item.name)">{{item.name}}</span>

我不确定 angular 是否能够解析$emit('pageChange',item.name)模板中的表达式。如果遇到任何问题,可以在控制器内部编写:

<span ng-repeat='item in webProjects' ng-click="setPageChange(item.name)">{{item.name}}</span>

在您的nav控制器中:

$scope.setPageChange = function (pageName) {
         $scope.$emit("pageChange",pageName);
   }

在您的AppCtrl中,收听事件并更新页面。

app.controller("AppCtrl", function($scope) {
    $scope.webProjects = webProjects;
    $scope.seoProjects = seoProjects;
//Here I set the initial value
    $scope.page = 'Comfort Homes of Athens';

    $scope.$on("pageChange", function (event, newPage){
         $scope.page = newPage;
    }
});
于 2014-09-19T23:59:48.330 回答
1

除了@KhanhTo 的回答,我还想向您指出另一个可以使用的工具,而不是 ngRoute;UI-路由器。这不是您原始问题的答案,但它是一个更好的解决方案,可以完全避免您的问题。

UI-Router增强了 ngRoute 的页面路由,更加以状态为中心。您转换到具有模板和可选控制器的状态。它发出自己的事件,例如$stateChangeStartor$stateChangeSuccesscommand $state.go(stateName)您可以使用函数或指令调用这些状态转换ui-sref="my.state({name: item.name})

UI-Router 是一个非常强大的工具,我不能在这里详细介绍,但是文档和社区很棒。

您的代码的简单重写可能如下所示。

web.html 的模板

<div class="wrapper">
    <aside class="boxModel">
        <div id="controller" class="container">
            <div class="topBox bluebg subNavBar"><h1 class="white">Projects</h1></div>
            <div ng-controller="nav" id="controls" class="botBox whitebg">
                <span ng-repeat='item in webProjects' ui-sref="app.web.page({name: {{item.name}})">
                    {{item.name}}
                 </span>
            </div>
        </div>
    </aside> 
    <section class="boxModel">

        <div ui-view class="container round box whitebg">
           <!-- Page content will go here -->
        </div>
    </section>
</div>

JavaScript

app.config(function($stateProvider) {
     $stateProvider
          .state('app', {
            abstract: true,
            template: '<div ui-view></div>', //Basic template 
            controller: "AppCtrl",
        }).state('app.home', {
            templateUrl: "templates/home.html",
            url: '/home'
        }).state('app.web',{
            templateUrl: "templates/web.html",
            url: '/web'
        }).state('app.web.page',{
            templateUrl: "templates/page.web.html",
            url: '/web/page/:name' //Note here the ':' means name will be a parameter in the url
        }).state('app.seo',{
            templateUrl: "templates/seo.html",
            url: '/seo'
        });
    });

app.controller('AppCtrl', function($scope){
    $scope.webProjects = webProjects;
    $scope.seoProjects = seoProjects;

    $scope.$on("$stateChangeStart", function (event, toState, toParams, fromState, fromParams){
        if(newState.name == 'app.web.page'){
            var pageName = newStateParams.name; //Variable name matches 
            $scope.linkText = fetchPageContent(pageName);
        }
    });
});

page.web.html 的模板

<h1>{{linkText}}</h1>

通过这些更改,您将能够重用控制器的相同实例。除了让您的分页内容更具可扩展性。

$scopes 注释

除了 $rootScope 之外,每个 $scope 都有一个父级。当您在视图中请求对象时,它将查看其 $scope 以查找引用。如果它没有引用,它将遍历其父范围并再次查看。这会一直发生,直到您到达 $rootScope。

如果您在视图中将某些内容分配给 $scope,它会将其分配给当前的 $scope,而不是在 $scope 链中搜索现有属性。这就是为什么ng-click="model.page = ..."有效;它查找模型的 $scope 链,然后分配给页面属性,同时ng-click="page = ..."直接分配给当前的 $scope。

控制器复用注意事项

据我所知,ngRoute 不支持嵌套视图。当你去一个新的路由时,它会破坏 $routeProvider 中指定的当前视图和控制器,然后为新视图实例化一个新控制器。UI-Router 支持嵌套状态(即具有子 $scopes 的子状态)。这允许我们创建一个可以在所有子状态中重用的父控制器。

于 2014-09-21T01:13:10.623 回答
-1

我认为这可能与对范围如何工作的一些误解有关。

ng-repeat创建自己的范围。尝试设置page时,角度会在 ng-repeat 的范围内创建它。

在您的AppCtrl中,在范围上创建一个对象,如下所示:

$scope.model = {};
$scope.model.page = 'Comfort Homes of Athens';//Default value

在您的 ng-click 上,请参阅model.page而不只是 page。然后,Angular 将遍历作用域来查找model.page,而不是仅仅在 ng-repeat 的本地作用域上创建一个属性。

<span ng-repeat='item in webProjects' ng-click="model.page='{{item.name}}'">{{item.name}}</span>

此外,每次更改页面时都会重新创建 AppCtrl。您可能应该使用服务来保持页面更改之间的状态

于 2014-08-06T02:02:15.800 回答