Наследование контроллера AngularJS

У AngularJS есть наследование контроллера на основе DOM, как указано в документах angular.

<div ng-controller="BaseController">
    <p>Base Controller Value: {{value}}</p>
    <button ng-click="updateValue()">Update In Base</button>
    <div ng-controller="DerivedController">
        <p>Derived Controller Value: {{value}}</p>
        <button ng-click="updateValue()">Update In Derived</button>
    </div>
</div>

Значение переменной "значение" присутствует только в BaseController. Исходя из этого, изменяя значение в методе в BaseController или DerivedController, я хочу, чтобы оба значения нужно было обновить. Но обновляется только отдельная переменная области.

Вот скрипка, демонстрирующая тот же пример: http://jsfiddle.net/6df6S/1/

Как можно изменить изменения на уровне для непосредственного дочернего элемента и непосредственного родителя текущей области.

Мы можем реализовать это, используя

$сфера. $Смотреть

Есть ли способ сделать это, не используя его или таких наблюдателей?

Изменить 1:

Используя $scope. $watch, вот что я имел в виду

$scope.$watch("value", function () {
   $scope.$broadcast("childChangeListener"); //Downwards to all children scopes
   $scope.$emit("parentChangeListener"); //Upwards to all parent scopes
});

Я искал способы, в которых значение будет обновляться во всех областях без использования такого механизма.

Ответ 1

Когда нескольким контроллерам нужен доступ к тем же данным, следует использовать service. Вы не должны полагаться на наследование области, так как ограничивают, как вы можете писать свой HTML. Например, в будущем вы решили, что DerivedController не должен быть дочерним элементом BaseController.

Ваша служба должна обычно предоставлять публичный API и скрывать реализацию. Это облегчает реорганизацию внутренних компонентов.

HTML:

<div ng-controller="BaseController">
    <p>Base Controller Value: {{model.getValue()}}</p>
    <button ng-click="model.updateValue('Value updated from Base')">Update In Base</button>
    <div ng-controller="DerivedController">
        <p>Derived Controller Value: {{model.getValue()}}</p>
        <button ng-click="model.updateValue('Value updated from Derived')">Update In Derived</button>
    </div>
</div>

JavaScript:

app.factory('sharedModel', function () {
    // private stuff
    var model = {
        value: "initial Value"
    };
    // public API
    return {
        getValue:    function() { 
           return model.value; 
        },
        updateValue: function(value) {
           model.value = value;
        }
    };
});

function BaseController($scope, sharedModel) {
    $scope.model = sharedModel;
}

function DerivedController($scope, sharedModel) {
    $scope.model = sharedModel;
}

Fiddle.

Кроме того, я не рекомендую использовать $rootScope для совместного использования между контроллерами.

Ответ 2

Связывание в вашей скрипке напрямую зависит от свойства. Наследование, которое вам нужно, может быть достигнуто за счет привязки данных к объекту в области.

http://jsfiddle.net/2Dtyq/

scope.shared = {}    
scope.shared.value = "Something"

Вместо просто

scope.value= "Something"

Что происходит?

В то время как DerivedController сконструирован, объем, передаваемый прототипом, наследуется от области BaseController.
Объект объекта DerivedController по-прежнему не имеет собственного свойства, называемого" значение". Поэтому он по-прежнему привязывается к свойству, полученному от родительской области.

Теперь, если вы нажмете кнопку Обновить в базе, она будет отображаться в обеих привязках. Когда вы нажмете кнопку Обновить в производной, в области DerviedController будет создано новое свойство с именем "значение". Поэтому привязка к свойству родительского значения нарушена. Все больше кликов по Обновить в базе не обновляет вторую привязку данных.
Помещение его в отдельный объект запрещает создание нового свойства, поэтому наследование сохраняется.

Ответ 3

Вы не можете напрямую ссылаться на строковое значение в дочернем контроллере. Из-за установки прототипного наследования свойство value в дочерней области (которое создается при использовании дочернего контроллера) создает это свойство в области дочернего элемента, а не обновляет свойство родительской области.

Ваша область применения не является моделью, поэтому мы должны избегать загрязнения переменной $scope множеством свойств. Создайте объект модели и создайте на нем дополнительные свойства. Затем этот объект можно передать вдоль дочерних контроллеров \scope.

Я изменил ваш jsfiddle, чтобы объяснить вышеприведенную точку.

Также я настоятельно рекомендую вам пройти эту страницу wiki, чтобы понять неприятности прототипного наследования.

Ответ 4

взгляните на метод $broadcast: $broadcast

Из документации:

Отправляет имя события вниз во все дочерние области (и их дети), уведомляющие зарегистрированных пользователей. $rootScope.Scope # $на слушателях.

Ответ 5

Используйте объекты вместо использования примитивного значения. В вашем случае определите объект, подобный этому

$scope.obj = {"value":"base"}; 

и попробуйте (obj.value). это будет работать.

Ответ 6

Это происходит из-за того, что ngController создает новую область $scope, а ссылка для значения - не то же самое. Вы можете решить это, используя свойство $parent, подобное этому:

<div ng-controller="BaseController">
    <p>Base Controller Value: {{value}}</p>
    <div ng-controller="DerivedController">
        <p>Derived Controller Value: {{$parent.value}}</p>
    </div>
</div>

И в DerivedController вы можете использовать что-то вроде этого: $scope.$parent.value

Но лучший способ реализовать это, чтобы использовать синтаксис controllerAs.

<div ng-controller="BaseController as BaseController ">
<p>Base Controller Value: {{BaseController.value}}</p>
<div ng-controller="DerivedController">
    <p>Derived Controller Value: {{BaseController.value}}</p>
</div>

И в DerivedController вы можете использовать что-то вроде этого: $scope.BaseController.value

Это дает читателю более читабельность, потому что вы знаете, что такое контроллер, на который вы ссылаетесь. Подробнее об этом в ngController Docs или Копаем в Angular s "контроллер как" от ToddMotto