使用 $rootscope 显示和隐藏
Show and hide using $rootscope
我的 index.html
模板中有一个搜索栏,我需要在某些页面上隐藏它。我正在使用 ui-router
和 $state
.
我可以完成这项工作的唯一方法是将 $rootscope
注入到我所有的控制器中 ng-hide: true
或 false
以在需要时打开或关闭它们。 (我真的只需要隐藏1或2页)
我认为这不是正确的方法,因为我所有的控制器现在都依赖并注入 $rootscope
。
还有其他方法吗?
例如
<div ng-controller="SearchCtrl">
<div ng-if="show">
...
</div>
</div>
app.controller('SearchCtrl', ['$state', '$scope', function($state, $scope) {
$scope.show = !$state.is('someState1') && !$state.is('someState2');
}
这不是很好的风格,但很简单。
让我们从全局控制器示例 GlobalCtrl
开始,它被添加到 body
或 html
标签,例如 ng-controller="GlobalCtrl
.
这样做将使我们能够在您的单个页面 Angular 应用程序中保持此 GlobalCtrl
的范围(因为您正在使用 ui-router
)并且我们可以避免使用 $rootScope
(实际上模仿了$rootScope
的用法)。
现在,在您的 GlobalCtrl
中定义如下内容:
// Using an object to avoid the scope inheritance problem of Angular
// https://github.com/angular/angular.js/wiki/Understanding-Scopes
$scope.globalData = {showSearchBar: true};
// This callback will be called everytime you change a page using ui-router state
$scope.$on('$stateChangeStart', function(event, toState, toParams) {
$scope.globalData.showSearchBar = true;
// Just check for your page where you do not want to display the search bar
// I'm using just an example like I don't want to display in contac-us page named state
if (toState.name == 'contact-us' || toParams.foo == "bar") {
$scope.globalData.showSearchBar = false;
}
});
现在,在您的 index.html
中,只需使用 ng-show
:
<div ng-show="globalData.showSearchBar">
<input type="text" ng-model="query" />
</div>
我不喜欢继续使用控制器,我认为最好以不依赖于另一个控制器的方式分离应用程序的每个部分。
我将使用服务来共享数据:
'use strict';
angular.module('yourModule')
/**
A service used to share resources between controllers
*/
.factory('Shared', [function () {
var resources = {};
resources.targetList = [];
resources.isVisibleDivA = true;
resources.isVisibleDivB = false;
return resources;
}]);
通过这种方式,注入服务后,您将始终能够与正确格式化布局所需的状态变量进行交互。
如果你想重用一个控制器,你只需添加一个模拟服务,你不需要依赖一个控制器。
在 ui-router
中,您可以使用 abstract states 创建层次结构。通过这种方式,您可以让父路由 具有搜索栏视图,而另一个则没有。你所有的实际路由都可以从这两个继承,你就完成了。
像这样
$stateProvider
.state('rootLayout', {
abstract: true,
// Note: abstract still needs a ui-view for its children to populate.
// You can simply add it inline here.
template: '<div><div ui-view="topbar"></div><div ui-view></div></div>'
})
.state('searchbarLayout', {
abstract: true,
views: {
'@rootLayout': {
// Note: abstract still needs a ui-view for its children to populate.
// You can simply add it inline here.
template: '<div ui-view></div>'
},
'topbar@rootLayout': {
template: '<input type="search" />'
},
}
});
您可以在表达式中使用 $root
从您的模板访问 $rootScope。喜欢:
<div ng-show="$root.appSettings.flag">
<span>Hello!</span>
</div>
我在应用程序的 运行 功能中注册了对象
.run([ '$rootScope', function ($rootScope) {
$rootScope.searchBar = { value: true };
}])
然后使用作用域改变了值。这将停止将 $rootscope 添加到每个控制器
$scope.searchBar.value = false;
在index.html页面设置值
<div ng-show="searchBar.value" ng-include src="'app/shared/search.html'"></div>
我的 index.html
模板中有一个搜索栏,我需要在某些页面上隐藏它。我正在使用 ui-router
和 $state
.
我可以完成这项工作的唯一方法是将 $rootscope
注入到我所有的控制器中 ng-hide: true
或 false
以在需要时打开或关闭它们。 (我真的只需要隐藏1或2页)
我认为这不是正确的方法,因为我所有的控制器现在都依赖并注入 $rootscope
。
还有其他方法吗?
例如
<div ng-controller="SearchCtrl">
<div ng-if="show">
...
</div>
</div>
app.controller('SearchCtrl', ['$state', '$scope', function($state, $scope) {
$scope.show = !$state.is('someState1') && !$state.is('someState2');
}
这不是很好的风格,但很简单。
让我们从全局控制器示例 GlobalCtrl
开始,它被添加到 body
或 html
标签,例如 ng-controller="GlobalCtrl
.
这样做将使我们能够在您的单个页面 Angular 应用程序中保持此 GlobalCtrl
的范围(因为您正在使用 ui-router
)并且我们可以避免使用 $rootScope
(实际上模仿了$rootScope
的用法)。
现在,在您的 GlobalCtrl
中定义如下内容:
// Using an object to avoid the scope inheritance problem of Angular
// https://github.com/angular/angular.js/wiki/Understanding-Scopes
$scope.globalData = {showSearchBar: true};
// This callback will be called everytime you change a page using ui-router state
$scope.$on('$stateChangeStart', function(event, toState, toParams) {
$scope.globalData.showSearchBar = true;
// Just check for your page where you do not want to display the search bar
// I'm using just an example like I don't want to display in contac-us page named state
if (toState.name == 'contact-us' || toParams.foo == "bar") {
$scope.globalData.showSearchBar = false;
}
});
现在,在您的 index.html
中,只需使用 ng-show
:
<div ng-show="globalData.showSearchBar">
<input type="text" ng-model="query" />
</div>
我不喜欢继续使用控制器,我认为最好以不依赖于另一个控制器的方式分离应用程序的每个部分。
我将使用服务来共享数据:
'use strict';
angular.module('yourModule')
/**
A service used to share resources between controllers
*/
.factory('Shared', [function () {
var resources = {};
resources.targetList = [];
resources.isVisibleDivA = true;
resources.isVisibleDivB = false;
return resources;
}]);
通过这种方式,注入服务后,您将始终能够与正确格式化布局所需的状态变量进行交互。
如果你想重用一个控制器,你只需添加一个模拟服务,你不需要依赖一个控制器。
在 ui-router
中,您可以使用 abstract states 创建层次结构。通过这种方式,您可以让父路由 具有搜索栏视图,而另一个则没有。你所有的实际路由都可以从这两个继承,你就完成了。
像这样
$stateProvider
.state('rootLayout', {
abstract: true,
// Note: abstract still needs a ui-view for its children to populate.
// You can simply add it inline here.
template: '<div><div ui-view="topbar"></div><div ui-view></div></div>'
})
.state('searchbarLayout', {
abstract: true,
views: {
'@rootLayout': {
// Note: abstract still needs a ui-view for its children to populate.
// You can simply add it inline here.
template: '<div ui-view></div>'
},
'topbar@rootLayout': {
template: '<input type="search" />'
},
}
});
您可以在表达式中使用 $root
从您的模板访问 $rootScope。喜欢:
<div ng-show="$root.appSettings.flag">
<span>Hello!</span>
</div>
我在应用程序的 运行 功能中注册了对象
.run([ '$rootScope', function ($rootScope) {
$rootScope.searchBar = { value: true };
}])
然后使用作用域改变了值。这将停止将 $rootscope 添加到每个控制器
$scope.searchBar.value = false;
在index.html页面设置值
<div ng-show="searchBar.value" ng-include src="'app/shared/search.html'"></div>