1

Я использую ngRoute для создания одноуровневого приложения с угловыми углами. Хотите перейти на компонентную версию.Угловой 1.5 компонентный родительский контроллер обновления через ngRoute

Проблема изолированных областей. Мне нужен доступ к реквизитам и методам основного контроллера. Попытка использовать привязки, но не работает. Я не могу найти проблему с этим. Это приложение прекрасно работает без использования компонентов. Когда я пытаюсь изменить представление домашней страницы на компонент, он сработает. Таковы основные части кода:

рамочным

<html ng-app="angularModule" > 
<body ng-controller="angularController as angCtrl" > 
    <div ng-show="angCtrl.user.isLoggedIn" >Sign Out</div> 
    <div ng-hide="angCtrl.user.isLoggedIn" cd-visible="angCtrl.showSignIn">Sign In</div> 
    <div id="contentLayer" class="contentLayer" ng-view ></div> 

шаблона домашнюю

<h1 class="pageLabel" >HomePage</h1> 
<blockquote>This can be anything. No bindings.</blockquote> 

angularController

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

app.directive ('cdVisible', 
    function() { 
     return function (scope, element, attr) { 
        scope.$watch (attr.cdVisible, 
         function (visible) { 
          element.css ('visibility', visible ? 'visible' : 'hidden'); 
         } 
        ); 
       }; 
    } 
); 

app.config ([ '$locationProvider', '$routeProvider', 
    function config ($locationProvider, $routeProvider) { 
     $locationProvider.hashPrefix ('!'); 
     $routeProvider 
     .when ('/sign-in', { 
      templateUrl: '/ng-sign-in', 
      controller:  signInController 
     }) 
     ... more routes 
     .when ('/home', { 
      template: '<home-page showSignIn="angCtrl.showSignIn" menuSelect="angCtrl.menuSelect" ></home-page>' 
     }) 
     .otherwise ('/home'); 
    } 
]); 

function homePageController() { 
    this.menuSelect ('Devices'); // this statement has no effect on angularController.menuSelection chrome shows it as an anonymous function 
    this.showSignIn = false; // this bombs: Expression 'undefined' in attribute 'showSignIn' used with directive 'homepage' is non-assignable! 
} 

app.component ('homePage', { 
    templateUrl: '/ng-homepage', 
    controller:  homePageController, 
    bindings: { 
     menuSelect: '&', 
     showSignIn: '=' 
    } 
}); 

app.controller ('angularController', [ '$http', '$window', '$location', 
    function ($http, $window, $location) { 
     var self = this; 
     this.user = { 
      "isLoggedIn":  false 
     }; 
     this.showSignIn = true; 
     this.menuSelection = ""; 
     this.errorMessage = ""; 
     this.menuSelect = 
      function (selection) { 
       self.menuSelection = selection; 
      }; 
     this.setUserData = 
      function (userData) { 
       self.user = userData; 
      }; 
     this.setShowSignIn = 
      function (show) { 
       self.showSignIn = show; 
      }; 
     this.menuSelect (''); 
     this.getUserData();  // I removed this for this post 
    } 
]); 

Я добавил комментарий к тому месту, где оно выдает исключение. Контроллер домашней страницы пытается обновить модель angularController. Первый ничего не делает, второй вызывает исключение. Что я делаю не так?

ответ

2

Прежде всего showSignIn является примитивным, поэтому угловое будет обрабатывать его точно так же, как и showSignIn="7+2". Если вам нужно изменить это значение внутри компонента, вы должны использовать объект с свойством showSignIn.

Теперь menuSelect немного жестче, вероятно, Chrome консоль показывает что-то вроде

function (locals) { 
    return parentGet(scope, locals); 
} 

Это потому, что вы просто передавая ссылку на angCtrl.menuSelect компоненту.

Для того, чтобы выполнить menuSelect функции из внутри homePageController вы должны сделать (в HTML):

<home-page menu-select="angCtrl.menuSelect(myMsg)"></home-page> 

, а затем вызвать его, как это в контроллере компонента:

this.menuSelect({ myMsg:"Devices" }) 

(myMsg) в HTML - это вызов угловой для возврата этой ссылки, затем в выполнении мы передаем параметр { myMsg:"Devices" }, чтобы соответствовать параметру в ссылке, которую мы только что сделали. Вы можете проверить this answer, что объясняет это более подробно.

0

В процессе чтения вашего ответа на меня набросилась одна ошибка: компонент домашней страницы маршрута/дома должен использовать меню show-sign-in для кебаба - выберите атрибуты, а не lower-camelCase, как было первоначально изначально закодировано.

Ваши предложения работали. Благодарю. Без компонентов я использовал прототипное наследование для доступа к свойствам и методам в родительской области. Из-за характера прототипного наследования javascript единственным способом изменения скаляров в родительской области является вызов методов setter в родительской области. По-видимому, здесь что-то похожее. Подробнее о prototypal inheritance в javascript.

Это упражнение доказательство концепции. Я хотел проверить свою способность обновлять свойства и объекты в родительской области от компонента, а также выполнять метод в родительской области. Этот пример обновляет скаляр в родительской области 2 различными способами:

  1. вставить его в объект, привязку к объекту и ссылаться на него, используя этот объект от компонента, как это делается с loginData.showSignIn булевой
  2. построить метод установки в родительской области и связываются с этим и вызывать сеттер из компонента, как это делается с menuSelect (который на самом деле не более чем сеттера для menuSelection)

и демонстрирует применение функции, делая так ,

Окончательный рабочий код: (шаблон Домашняя страница не меняется)

рамки

<html ng-app="angularModule" > 
<body ng-controller="angularController as angCtrl" > 
    <div ng-show="angCtrl.user.isLoggedIn" >Sign Out</div> 
    <div ng-hide="angCtrl.user.isLoggedIn" cd-visible="angCtrl.loginData.showSignIn">Sign In</div> 
    <div id="contentLayer" class="contentLayer" ng-view ></div> 

angularController

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

app.directive ('cdVisible', 
    function() { 
     return function (scope, element, attr) { 
        scope.$watch (attr.cdVisible, 
         function (visible) { 
          element.css ('visibility', visible ? 'visible' : 'hidden'); 
         } 
        ); 
       }; 
    } 
); 

app.config ([ '$locationProvider', '$routeProvider', 
    function config ($locationProvider, $routeProvider) { 
     $locationProvider.hashPrefix ('!'); 
     $routeProvider 
      .when ('/sign-in', { 
       templateUrl: '/ng-sign-in', 
       controller:  signInController 
      }) 
       ... more routes 
      .when ('/home', { 
       template: '<home-page login-data="angCtrl.loginData" menu-select="angCtrl.menuSelect(mySelection)" ></home-page>' 
      }) 
      .otherwise ('/home'); 
     } 
]); 

function homePageController() { 
    this.menuSelect ( { mySelection: 'Overview' }); 
    this.loginData.showSignIn = true; 
} 

app.component ('homePage', { 
    templateUrl: '/ng-homepage', 
    controller:  homePageController, 
    restrict:  'E', 
    bindings: { 
     menuSelect: '&', 
     loginData: '=' 
    } 
}); 

app.controller ('angularController', [ '$http', '$window', '$location', 
    function ($http, $window, $location) { 
     var self = this; 
     this.user = { 
      "isLoggedIn":  false 
     }; 
     this.loginData = { 
      "showSignIn":  false 
     }; 
     this.menuSelection = ""; 
     this.errorMessage = ""; 
     this.menuSelect = 
      function (selection) { 
       self.menuSelection = selection; 
      }; 
     this.setUserData = 
      function (userData) { 
       self.user = userData; 
      }; 
     this.setShowSignIn = 
      function (show) { 
       self.showSignIn = show; 
      }; 
     this.menuSelect (''); 
     this.getUserData();  // I removed this for this post 
    } 
]);