AngularJS 부분보기를 기반으로 헤더를 동적으로 변경하는 방법은 무엇입니까?
ng-view를 사용하여 AngularJS 부분보기를 포함하고 있으며 포함 된보기를 기반으로 페이지 제목과 h1 헤더 태그를 업데이트하고 싶습니다. 이것들은 부분 뷰 컨트롤러의 범위를 벗어 났으므로 컨트롤러의 데이터 세트에 바인딩하는 방법을 알 수 없습니다.
ASP.NET MVC 인 경우 @ViewBag를 사용 하여이 작업을 수행 할 수 있지만 AngularJS의 해당 기능을 알 수 없습니다. 공유 서비스, 이벤트 등을 검색했지만 여전히 작동하지 않습니다. 내 예제를 수정하여 작동하도록하는 방법은 대단히 감사하겠습니다.
내 HTML :
<html data-ng-app="myModule">
<head>
<!-- include js files -->
<title><!-- should changed when ng-view changes --></title>
</head>
<body>
<h1><!-- should changed when ng-view changes --></h1>
<div data-ng-view></div>
</body>
</html>
내 JavaScript :
var myModule = angular.module('myModule', []);
myModule.config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/test1', {templateUrl: 'test1.html', controller: Test1Ctrl}).
when('/test2', {templateUrl: 'test2.html', controller: Test2Ctrl}).
otherwise({redirectTo: '/test1'});
}]);
function Test1Ctrl($scope, $http) { $scope.header = "Test 1";
/* ^ how can I put this in title and h1 */ }
function Test2Ctrl($scope, $http) { $scope.header = "Test 2"; }
<html>
레벨 에서 컨트롤러를 정의 할 수 있습니다.
<html ng-app="app" ng-controller="titleCtrl">
<head>
<title>{{ Page.title() }}</title>
...
service :를 작성 Page
하고 제어기에서 수정하십시오.
myModule.factory('Page', function() {
var title = 'default';
return {
title: function() { return title; },
setTitle: function(newTitle) { title = newTitle }
};
});
Page
컨트롤러에서 'Page.setTitle ()'을 삽입 하고 호출하십시오.
구체적인 예는 다음과 같습니다. http://plnkr.co/edit/0e7T6l
라우팅을 사용하는 경우 페이지 제목을 설정하는 좋은 방법을 발견했습니다.
자바 스크립트 :
var myApp = angular.module('myApp', ['ngResource'])
myApp.config(
['$routeProvider', function($routeProvider) {
$routeProvider.when('/', {
title: 'Home',
templateUrl: '/Assets/Views/Home.html',
controller: 'HomeController'
});
$routeProvider.when('/Product/:id', {
title: 'Product',
templateUrl: '/Assets/Views/Product.html',
controller: 'ProductController'
});
}]);
myApp.run(['$rootScope', function($rootScope) {
$rootScope.$on('$routeChangeSuccess', function (event, current, previous) {
$rootScope.title = current.$$route.title;
});
}]);
HTML :
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<title ng-bind="'myApp — ' + title">myApp</title>
...
편집 : ng-bind
curls 대신 속성을 사용하여 {{}}
로드시 표시되지 않음
자바 스크립트로 제목을 직접 설정할 수도 있습니다. 즉,
$window.document.title = someTitleYouCreated;
이것은 데이터 바인딩을 가지고 있지 않지만, 퍼팅 때 충분 ng-app
에 <html>
태그하는 것은 문제가있다. 예를 들어 <head>
정확히 한 곳에 정의 된 JSP 템플리트를 사용 하지만 둘 이상의 앱이 있습니다.
선언 ng-app
온 html
요소 것은 모두를위한 루트 범위 제공 head
및 body
.
따라서 컨트롤러에서 다음 $rootScope
에 헤더 속성을 삽입 하고 설정하십시오.
function Test1Ctrl($rootScope, $scope, $http) { $rootScope.header = "Test 1"; }
function Test2Ctrl($rootScope, $scope, $http) { $rootScope.header = "Test 2"; }
그리고 당신의 페이지에서 :
<title ng-bind="header"></title>
angularjs-viewhead 모듈 은 사용자 지정 지시문 만 사용하여 뷰별로 제목을 설정하는 메커니즘을 보여줍니다.
컨텐츠가 이미 뷰 제목 인 기존 뷰 요소에 적용 할 수 있습니다.
<h2 view-title>About This Site</h2>
... 독립형 요소로 사용할 수 있습니다.이 경우 렌더링 된 문서에서 요소가 보이지 않으며보기 제목을 설정하는 데만 사용됩니다.
<view-title>About This Site</view-title>
이 지시문의 내용은 루트 범위에서로 사용할 viewTitle
수 있으므로 다른 변수와 마찬가지로 제목 요소에서 사용할 수 있습니다.
<title ng-bind-template="{{viewTitle}} - My Site">My Site</title>
루트 범위를 "볼"수있는 다른 지점에서도 사용할 수 있습니다. 예를 들면 다음과 같습니다.
<h1>{{viewTitle}}</h1>
이 솔루션을 사용하면 나머지 프레젠테이션을 제어하는 데 사용되는 것과 동일한 메커니즘 인 AngularJS 템플릿을 통해 제목을 설정할 수 있습니다. 이를 통해이 프리젠 테이션 로직으로 컨트롤러를 복잡하게 만들 필요가 없습니다. 컨트롤러 는 제목 을 알리는 데 사용할 데이터를 제공해야 하지만 템플릿은 제목을 표시하는 방법을 최종적으로 결정하고 식 보간 및 필터를 사용하여 스코프 데이터를 정상적으로 바인딩 할 수 있습니다.
(면책 조항 : 나는이 모듈의 저자이지만 다른 사람 이이 문제를 해결하는 데 도움이되기를 희망하면서 여기에서 참조하고 있습니다.)
다음은 리소스 별 페이지 제목을 설정하기 위해 컨트롤러에 $ rootScope를 주입 할 필요가없는 적합한 솔루션입니다.
마스터 템플릿에서 :
<html data-ng-app="myApp">
<head>
<title data-ng-bind="page.title"></title>
...
라우팅 구성에서 :
$routeProvider.when('/products', {
title: 'Products',
templateUrl: '/partials/products.list.html',
controller: 'ProductsController'
});
$routeProvider.when('/products/:id', {
templateUrl: '/partials/products.detail.html',
controller: 'ProductController'
});
그리고 실행 블록에서 :
myApp.run(['$rootScope', function($rootScope) {
$rootScope.page = {
setTitle: function(title) {
this.title = title + ' | Site Name';
}
}
$rootScope.$on('$routeChangeSuccess', function(event, current, previous) {
$rootScope.page.setTitle(current.$$route.title || 'Default Title');
});
}]);
마지막으로 컨트롤러에서 :
function ProductController($scope) {
//Load product or use resolve in routing
$scope.page.setTitle($scope.product.name);
}
jkoreska의 솔루션은 미리 제목을 알고 있으면 완벽하지만 리소스 등에서 얻은 데이터를 기반으로 제목을 설정해야 할 수도 있습니다.
내 솔루션에는 단일 서비스가 필요합니다. rootScope는 모든 DOM 요소의 기본이므로 언급 된 사람과 같이 html 요소에 컨트롤러를 배치 할 필요가 없습니다.
Page.js
app.service('Page', function($rootScope){
return {
setTitle: function(title){
$rootScope.title = title;
}
}
});
index.jade
doctype html
html(ng-app='app')
head
title(ng-bind='title')
// ...
제목을 변경해야하는 모든 컨트롤러
app.controller('SomeController', function(Page){
Page.setTitle("Some Title");
});
제목이나 메타 설명을 동적으로 설정할 수있는 깔끔한 방법입니다. 예를 들어 ui-router를 사용하지만 ngRoute를 같은 방식으로 사용할 수 있습니다.
var myApp = angular.module('myApp', ['ui.router'])
myApp.config(
['$stateProvider', function($stateProvider) {
$stateProvider.state('product', {
url: '/product/{id}',
templateUrl: 'views/product.html',
resolve: {
meta: ['$rootScope', '$stateParams', function ($rootScope, $stateParams) {
var title = "Product " + $stateParams.id,
description = "Product " + $stateParams.id;
$rootScope.meta = {title: title, description: description};
}]
// Or using server side title and description
meta: ['$rootScope', '$stateParams', '$http', function ($rootScope, $stateParams, $http) {
return $http({method: 'GET', url: 'api/product/ + $stateParams.id'})
.then (function (product) {
$rootScope.meta = {title: product.title, description: product.description};
});
}]
}
controller: 'ProductController'
});
}]);
HTML :
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<title ng-bind="meta.title + ' | My App'">myApp</title>
...
또는 ui-router를 사용하는 경우 :
index.html
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<title ng-bind="$state.current.data.title || 'App'">App</title>
라우팅
$stateProvider
.state('home', {
url: '/',
templateUrl: 'views/home.html',
data: {
title: 'Welcome Home.'
}
}
맞춤형 이벤트 기반 솔루션
여기에 다른 사람들이 언급하지 않은 또 다른 접근법이 있습니다 (이 글을 쓰는 현재).
다음과 같이 사용자 정의 이벤트를 사용할 수 있습니다.
// your index.html template
<html ng-app="app">
<head>
<title ng-bind="pageTitle">My App</title>
// your main app controller that is declared on the <html> element
app.controller('AppController', function($scope) {
$scope.$on('title-updated', function(newTitle) {
$scope.pageTitle = newTitle;
});
});
// some controller somewhere deep inside your app
mySubmodule.controller('SomeController', function($scope, dynamicService) {
$scope.$emit('title-updated', dynamicService.title);
});
이 방법은 추가 서비스를 작성하지 않아도되고 제목을 설정해야하는 모든 컨트롤러에 삽입 할 필요가 없으며을 사용하지 않는 이점이 있습니다 $rootScope
. 또한 코드 제목과 같이 동적 제목을 설정할 수 있습니다. 최소한 아는 한 라우터의 구성 객체에서 사용자 정의 데이터 속성을 사용하면 불가능합니다.
title
태그 가 포함 된 ngApp이없는 시나리오의 경우 창 제목을 설정해야하는 컨트롤러에 서비스를 삽입하십시오.
var app = angular.module('MyApp', []);
app.controller('MyController', function($scope, SomeService, Title){
var serviceData = SomeService.get();
Title.set("Title of the page about " + serviceData.firstname);
});
app.factory('SomeService', function ($window) {
return {
get: function(){
return { firstname : "Joe" };
}
};
});
app.factory('Title', function ($window) {
return {
set: function(val){
$window.document.title = val;
}
};
});
실제 예 ... http://jsfiddle.net/8m379/1/
asp.net 웹 양식과 같은 제목 요소를 제어 할 수없는 경우 여기에 사용할 수있는 것이 있습니다
var app = angular.module("myApp")
.config(function ($routeProvider) {
$routeProvider.when('/', {
title: 'My Page Title',
controller: 'MyController',
templateUrl: 'view/myView.html'
})
.otherwise({ redirectTo: '/' });
})
.run(function ($rootScope) {
$rootScope.$on("$routeChangeSuccess", function (event, currentRoute, previousRoute) {
document.title = currentRoute.title;
});
});
사용하여 간단하고 더러운 방법 $rootScope
:
<html ng-app="project">
<head>
<title ng-bind="title">Placeholder title</title>
컨트롤러에서 제목을 만드는 데 필요한 데이터가 있으면 다음을 수행하십시오.
$rootScope.title = 'Page X'
이러한 답변 중 어느 것도 직관적으로 보이지 않았 으므로이 작업을 수행하기위한 작은 지시문을 만들었습니다. 이 방법을 사용하면 일반적으로 페이지에서 제목을 선언 할 수 있으며 동적 일 수도 있습니다.
angular.module('myModule').directive('pageTitle', function() {
return {
restrict: 'EA',
link: function($scope, $element) {
var el = $element[0];
el.hidden = true; // So the text not actually visible on the page
var text = function() {
return el.innerHTML;
};
var setTitle = function(title) {
document.title = title;
};
$scope.$watch(text, setTitle);
}
};
});
물론 자신의 이름과 일치하도록 모듈 이름을 변경해야합니다.
그것을 사용하려면 일반 <title>
태그 와 마찬가지로보기에 이것을 던져 넣으십시오 .
<page-title>{{titleText}}</page-title>
동적으로 필요하지 않은 경우 일반 텍스트 만 포함 할 수도 있습니다.
<page-title>Subpage X</page-title>
또는 속성을 사용하여 IE에보다 친숙하게 만들 수 있습니다.
<div page-title>Title: {{titleText}}</div>
물론 Angular 코드를 포함하여 원하는 텍스트를 태그에 넣을 수 있습니다. 이 예에서는 $scope.titleText
현재 사용자 정의 제목 태그가있는 컨트롤러를 찾습니다 .
페이지에 여러 페이지 제목 태그가 없는지 확인하십시오. 그렇지 않으면 서로 충돌 할 수 있습니다.
Plunker의 예는 여기 http://plnkr.co/edit/nK63te7BSbCxLeZ2ADHV 입니다. 타이틀 변경 사항을 보려면 zip을 다운로드하여 로컬로 실행해야합니다.
제목 변경을 수행하는 다른 방법이 있습니다. 아마도 무제한 페이지를 처리 할 수있는 팩토리 함수만큼 확장 가능하지는 않지만 이해하기가 더 쉬웠습니다.
내 index.html에서 다음과 같이 시작했습니다.
<!DOCTYPE html>
<html ng-app="app">
<head>
<title ng-bind-template="{{title}}">Generic Title That You'll Never See</title>
그런 다음 "nav.html"이라는 부분을 만들었습니다.
<div ng-init="$root.title = 'Welcome'">
<ul class="unstyled">
<li><a href="#/login" ng-click="$root.title = 'Login'">Login</a></li>
<li><a href="#/home" ng-click="$root.title = 'Home'">Home</a></li>
<li><a href="#/admin" ng-click="$root.title = 'Admin'">Admin</a></li>
<li><a href="#/critters" ng-click="$root.title = 'Crispy'">Critters</a></li>
</ul>
</div>
그런 다음 "index.html"로 돌아가서 ng-include와 ng-view를 사용하여 nav.html을 추가했습니다.
<body class="ng-cloak" ng-controller="MainCtrl">
<div ng-include="'partials/nav.html'"></div>
<div>
<div ng-view></div>
</div>
그 망토는? 이 답변과 관련이 없지만로드가 완료 될 때까지 페이지를 숨 깁니다. 멋지게 만집니다 :) 방법 알아보기 : Angularjs-ng-cloak / ng-show 요소 깜박임
기본 모듈은 다음과 같습니다. "app.js"라는 파일에 넣었습니다.
(function () {
'use strict';
var app = angular.module("app", ["ngResource"]);
app.config(function ($routeProvider) {
// configure routes
$routeProvider.when("/", {
templateUrl: "partials/home.html",
controller:"MainCtrl"
})
.when("/home", {
templateUrl: "partials/home.html",
controller:"MainCtrl"
})
.when("/login", {
templateUrl:"partials/login.html",
controller:"LoginCtrl"
})
.when("/admin", {
templateUrl:"partials/admin.html",
controller:"AdminCtrl"
})
.when("/critters", {
templateUrl:"partials/critters.html",
controller:"CritterCtrl"
})
.when("/critters/:id", {
templateUrl:"partials/critter-detail.html",
controller:"CritterDetailCtrl"
})
.otherwise({redirectTo:"/home"});
});
}());
모듈의 끝 부분을 살펴보면 : id를 기반으로 한 critter-detail 페이지가 있음을 알 수 있습니다. Crispy Critters 페이지에서 사용되는 부분입니다. [코니, 알아요-아마도 모든 종류의 치킨 너겟을 기념하는 사이트 일 것입니다.) 어쨌든, 사용자가 링크를 클릭 할 때 제목을 업데이트 할 수 있습니다. 위의 nav.html에서 보듯이 $ root.title 업데이트가 진행되는 곳입니다.
<a href="#/critters/1" ng-click="$root.title = 'Critter 1'">Critter 1</a>
<a href="#/critters/2" ng-click="$root.title = 'Critter 2'">Critter 2</a>
<a href="#/critters/3" ng-click="$root.title = 'Critter 3'">Critter 3</a>
바람이 불거 워 죄송하지만 세부 정보를 제공하는 게시물을 선호합니다. AngularJS 문서의 예제 페이지가 오래되었으며 0.9 버전의 ng-bind-template을 보여줍니다. 그다지 다르지 않다는 것을 알 수 있습니다.
사후 생각 : 당신은 이것을 알고 있지만 다른 사람을 위해 여기 있습니다. index.html의 맨 아래에 app.js를 모듈과 함께 포함시켜야합니다.
<!-- APP -->
<script type="text/javascript" src="js/app.js"></script>
</body>
</html>
이 문제를 해결해야 할 때 ng-app
페이지의 html
태그를 배치 할 수 없었 으므로 서비스를 사용하여 해결했습니다.
angular.module('myapp.common').factory('pageInfo', function ($document) {
// Public API
return {
// Set page <title> tag. Both parameters are optional.
setTitle: function (title, hideTextLogo) {
var defaultTitle = "My App - and my app's cool tagline";
var newTitle = (title ? title : defaultTitle) + (hideTextLogo ? '' : ' - My App')
$document[0].title = newTitle;
}
};
});
각도 UI 라우터를위한 간단한 솔루션 :
HTML :
<html ng-app="myApp">
<head>
<title ng-bind="title"></title>
.....
.....
</head>
</html>
App.js> myApp.config 블록
$stateProvider
.state("home", {
title: "My app title this will be binded in html title",
url: "/home",
templateUrl: "/home.html",
controller: "homeCtrl"
})
App.js> myApp.run
myApp.run(['$rootScope','$state', function($rootScope,$state) {
$rootScope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState, fromParams) {
$rootScope.title = $state.current.title;
console.log($state);
});
}]);
Michael Bromley 에서 영감을 얻은 맞춤형 이벤트 기반 솔루션
$ scope로 작동시킬 수 없었기 때문에 rootScope를 사용해 보았습니다. 아마 더럽습니다 ... (특히 이벤트를 등록하지 않은 페이지를 새로 고치는 경우)
그러나 나는 일이 느슨하게 결합되는 방법에 대한 아이디어를 정말로 좋아합니다.
angularjs 1.6.9를 사용하고 있습니다.
index.run.js
angular
.module('myApp')
.run(runBlock);
function runBlock($rootScope, ...)
{
$rootScope.$on('title-updated', function(event, newTitle) {
$rootScope.pageTitle = 'MyApp | ' + newTitle;
});
}
anyController.controller.js
angular
.module('myApp')
.controller('MainController', MainController);
function MainController($rootScope, ...)
{
//simple way :
$rootScope.$emit('title-updated', 'my new title');
// with data from rest call
TroncQueteurResource.get({id:tronc_queteur_id}).$promise.then(function(tronc_queteur){
vm.current.tronc_queteur = tronc_queteur;
$rootScope.$emit('title-updated', moment().format('YYYY-MM-DD') + ' - Tronc '+vm.current.tronc_queteur.id+' - ' +
vm.current.tronc_queteur.point_quete.name + ' - '+
vm.current.tronc_queteur.queteur.first_name +' '+vm.current.tronc_queteur.queteur.last_name
);
});
....}
index.html
<!doctype html>
<html ng-app="myApp">
<head>
<meta charset="utf-8">
<title ng-bind="pageTitle">My App</title>
그것은 나를 위해 일하고있다 :)
다른 사람들에게는 더 나은 방법이 있지만 각 뷰 / 템플릿마다 고유 한 컨트롤러가 있기 때문에 컨트롤러에서 $ rootScope를 사용할 수있었습니다. 각 컨트롤러에 $ rootScope를 주입해야합니다. 이것이 이상적이지 않을 수도 있지만, 그것은 나를 위해 기능하고 있으므로 전달해야한다고 생각했습니다. 페이지를 검사하면 제목 태그에 ng-binding이 추가됩니다.
컨트롤러 예 :
myapp.controller('loginPage', ['$scope', '$rootScope', function ($scope, $rootScope) {
// Dynamic Page Title and Description
$rootScope.pageTitle = 'Login to Vote';
$rootScope.pageDescription = 'This page requires you to login';
}]);
Index.html 헤더 예 :
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<meta name="description" content="{{pageDescription}}">
<meta name="author" content="">
<link rel="shortcut icon" href="../../assets/ico/favicon.ico">
<base href="/">
<title>{{pageTitle}}</title>
pageTitle 및 pageDescription을 REST 호출에서 데이터 리턴과 같은 동적 값으로 설정할 수도 있습니다.
$scope.article = restCallSingleArticle.get({ articleID: $routeParams.articleID }, function() {
// Dynamic Page Title and Description
$rootScope.pageTitle = $scope.article.articletitle;
$rootScope.pageDescription = $scope.article.articledescription;
});
다시 말하지만, 다른 사람들은 이것에 접근하는 방법에 대해 더 나은 아이디어를 가질 수 있지만 사전 렌더링을 사용하고 있기 때문에 내 요구가 충족되고 있습니다.
그의 솔루션에 대해 tosh shimayama 에게 감사합니다 .
나는로 서비스를 똑바로 넣어 너무 깨끗하지라고 생각 $scope
때문에 여기에 내 약간의 변화입니다 : http://plnkr.co/edit/QJbuZZnZEDOBcYrJXWWs
컨트롤러 (원래 답변에서 약간 바보 같은 것처럼 보임)는 ActionBar 객체를 만들고이 객체는 $ scope에 채워집니다.
객체는 실제로 서비스를 쿼리합니다. 또한 $ scope에서 템플릿 URL을 설정하는 호출을 숨기고 대신 다른 컨트롤러가 URL을 설정하는 데 사용할 수 있습니다.
Hash 는 지금까지 가장 좋은 답변을 얻었지만 아래 솔루션을 통해 다음과 같은 이점을 추가하여 이상적입니다.
- 시계를 추가하지 않아 속도가 느려질 수 있습니다
- 실제로 컨트롤러에서 수행 한 작업을 자동화합니다.
- 여전히 원하는 경우 컨트롤러에서 액세스 할 수 있습니다.
- 추가 주사 불필요
라우터에서 :
.when '/proposals',
title: 'Proposals',
templateUrl: 'proposals/index.html'
controller: 'ProposalListCtrl'
resolve:
pageTitle: [ '$rootScope', '$route', ($rootScope, $route) ->
$rootScope.page.setTitle($route.current.params.filter + ' ' + $route.current.title)
]
실행 블록에서 :
.run(['$rootScope', ($rootScope) ->
$rootScope.page =
prefix: ''
body: ' | ' + 'Online Group Consensus Tool'
brand: ' | ' + 'Spokenvote'
setTitle: (prefix, body) ->
@prefix = if prefix then ' ' + prefix.charAt(0).toUpperCase() + prefix.substring(1) else @prifix
@body = if body then ' | ' + body.charAt(0).toUpperCase() + body.substring(1) else @body
@title = @prefix + @body + @brand
])
내가 찾은 더 좋고 역동적 인 솔루션은 $ watch를 사용하여 변수 변경 사항을 추적하고 제목을 업데이트하는 것입니다.
'Programing' 카테고리의 다른 글
C #에서 var 키워드 사용 (0) | 2020.02.21 |
---|---|
파이썬에서 목록의 시작 부분에 정수 추가 (0) | 2020.02.21 |
<10 줄의 간단한 코드로 할 수있는 가장 멋진 일은 무엇입니까? (0) | 2020.02.21 |
완벽한 JPA 엔터티 만들기 (0) | 2020.02.21 |
PHP 키워드 'var'의 기능은 무엇입니까? (0) | 2020.02.21 |