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-switch内部进行ng-click而不是相反。并且他们的例子中也没有使用路由。角度还是新的,也许是我还没遇到过的东西。
应用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';
});
答案 0 :(得分:4)
不幸的是,ng-repeat
创建了子级范围,这些范围是父级控制器(ng-controller="nav"
)的父级控制器(<section>
)的兄弟姐妹,而ng-switch
所在的ng-controller="nav"
< strong>不是 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>
只是为了理解角度范围。
model
我不推荐使用此解决方案,因为它非常难看。 @ link64的解决方案更好,但我认为<span ng-repeat='item in webProjects' ng-click="$emit('pageChange',item.name)">{{item.name}}</span>
的继承是如此隐式并创建一个紧密耦合的代码。在这里,我提出另一个解决方案,我希望通过发布一个事件来更好:
$emit('pageChange',item.name)
我不确定angular是否能够解析模板中的<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;
}
});
中,收听活动并更新页面。
{{1}}
答案 1 :(得分:1)
除了@ KhanhTo的答案之外,我还想指出你使用另一种工具来代替ngRoute; UI的路由器。这不是您原始问题的答案,但它是一个更好的解决方案,完全避免您的问题。
UI-Router 增强了ngRoute的页面路由,并且更加集中于各州。您转换到具有模板和可选控制器的状态。它会发出自己的事件,例如$stateChangeStart
或$stateChangeSuccess
。您可以使用函数command $state.go(stateName)
或指令ui-sref="my.state({name: item.name})
UI-Router是一个非常强大的工具,我不能在这里详细介绍所有细节,但文档和社区很棒。
对代码的简单重写可能如下所示。
<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>
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);
}
});
});
<h1>{{linkText}}</h1>
通过这些更改,您将能够重用控制器的同一实例。除了允许您的分页内容更具可伸缩性。
除$ rootScope外,每个$ scope都有一个父级。当您在视图中请求对象时,它将查看其$ scope以查找引用。如果它没有引用,它将遍历到其父作用域并再次查看。这种情况发生在你到达$ rootScope之前。
如果在视图中为$ scope分配内容,它会将其分配给当前的$ scope,而不是搜索现有属性的$ scope链。这就是ng-click="model.page = ..."
有效的原因;它查找模型的$ scope chaing然后分配给页面属性,而ng-click="page = ..."
直接分配给当前的$ scope。
据我所知,ngRoute不支持嵌套视图。当您转到新路由时,它将销毁$ routeProvider中指定的当前视图和控制器,然后为新视图实例化一个新控制器。 UI-Router支持嵌套状态(即具有子$ scopes的子状态)。这允许我们创建一个可以在所有子状态中重用的父控制器。
答案 2 :(得分:-1)
我认为这可能与对范围如何运作的误解有关。
ng-repeat
创建自己的范围。尝试设置page
时,angular会在ng-repeat的范围内创建它。
在AppCtrl
中,在范围内创建一个对象,如下所示:
$scope.model = {};
$scope.model.page = 'Comfort Homes of Athens';//Default value
点击后,请参阅model.page
而不是页面。然后,Angular将遍历范围以查找model.page
,而不是仅在ng-repeat的本地范围内创建属性。
<span ng-repeat='item in webProjects' ng-click="model.page='{{item.name}}'">{{item.name}}</span>
此外,每次更改页面时都会重新创建AppCtrl。您可能应该使用服务在页面更改之间保持状态