2016-11-08 5 views
0

Я пытаюсь узнать о угловых компонентах, но у меня возникают проблемы с их работой в конфигурации вложенных компонентов. В принципе, я хочу, чтобы родительский компонент периодически обновлял значение. Затем я хочу, чтобы внутренний дочерний компонент привязывался к значению в родительском элементе и вызывал вызов $ onChanges при изменении значения.Устранение неисправностей Угловые компоненты

Я сделал jsFiddle, демонстрируя то, что я пытаюсь выполнить. Родительский компонент, похоже, работает и отображает обновленное значение, но по какой-то причине дочерний компонент вообще не отображается. Вот код, я использую для достижения этой цели:

let app = angular.module('app', []); 

class ParentController { 
    constructor($interval) { 
    this.value = 0; 

    $interval(() => this.value++, 1000); 
    } 
} 

let ParentComponent = { 
    controller: ParentController, 
    template: `<div>parent value: {{$ctrl.value}}</div>` 
}; 

app.component('parent', ParentComponent); 

class ChildController { 
    $onChanges(changesObj) { 
    console.log(changesObj); 
    } 
} 

let ChildComponent = { 
    bindings: { 
    value: '=' 
    }, 
    controller: ChildController, 
    require: { 
    parent: '^^parent' 
    }, 
    template: `<div>child value: {{$ctrl.value}}</div>` 
}; 

app.component('child', ChildComponent); 

И HTML:

<div ng-app="app"> 
    <parent> 
    <child value="$ctrl.parent.value"></child> 
    </parent> 
</div> 

Я делаю что-то неправильно, или то, что я пытаюсь выполнить не представляется возможным?

ответ

0

Дело в том, что все, что внутри них обычно заменяется, если вы не используете директиву 'ng-transclude'.

Чтобы получить свой дочерний элемент появится, вам понадобятся следующие изменения:

let ParentComponent = { 
    controller: ParentController, 
    transclude: true, 
    template: `<div>parent value: {{$ctrl.value}}</div><div ng-transclude></div>` 
}; 

Для уточнения, добавления transclude: true к компоненту объекта, а также элемент с ng-transclude директивы в шаблоне. Независимо от того, какой элемент имеет директиву ng-transclude, его содержимое будет заменено на все, что находится в теге <parent>.

Это будет только ваш ребенок компонент для визуализации, у вас еще есть другая ошибка в вашем HTML в том, что вы пытаетесь использовать

<child value="$ctrl.parent.value"></child> 

Который, в JavaScript, эквивалентно $scope.$ctrl.parent.value, который не определен ,

Просто измените HTML на:

<div ng-app="app"> 
    <parent> 
    <child></child> 
    </parent> 
</div> 

И компонент ребенка:

let ChildComponent = { 
    controller: ChildController, 
    require: { 
    parent: '^^parent' 
    }, 
    template: `<div>child value: {{$ctrl.parent.value}}</div>` 
}; 

И тогда вы все хорошо!

EDIT (с комментариями): Для того, чтобы вызвать изменение звонка при изменении родителя значение, вам нужно будет заменить ваш ChildController следующим:

let ChildController = function (scope) { 
    scope.$watch('$ctrl.parent.value', function (newValue, oldValue) { 
    console.log(newValue); 
    }); 
}; 

Это добавляет часы на контроллере ребенка который будет вызывать функцию каждый раз, когда изменяется parent.value.

+0

Спасибо за вашу помощь. Я не знал о опции transclude. Один вопрос: знаете ли вы, есть ли способ, с помощью которого дочерний компонент ChildComponent запускает $ onChanges при изменении родительского значения? – snusnu

+0

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

+0

Игнорировать мой последний комментарий, это действительно возможно. Проверьте мое последнее редактирование! –

0

Я сделал som модификации вашего кода. существует другой способ достижения того, что вы хотите сделать. вот мой код. Я попытаюсь объяснить, как это должно быть сделано.

let app = angular.module('app', []); 

     class ParentController { 
      constructor($interval) { 
      this.value = 0; 

      $interval(() => this.value++, 1000); 
      } 
     } 

     let ParentComponent = { 
      controller: ParentController, 
//here is the important edit. loading child component inside the parent component 
      template: `<div> 
         parent value: {{$ctrl.value}} 
         <child value="$ctrl.value"></child> 
        </div>` 
     }; 

     app.component('parent', ParentComponent); 

     class ChildController { 
      $onChanges(changesObj) { 
      if(changesObj.hasOwnProperty('value')){ 
       this.value=changesObj.value.currentValue //this referes to current scope. 
      } 
      } 
     } 

     let ChildComponent = { 
      bindings: { 
      value: '<' 
      }, 
      controller: ChildController, 
      require: { 
      //parent: '^^parent' no need for this. we will use $onChanges 
      }, 
      template: `<div>child value: {{$ctrl.value}}</div>` 
     }; 

     app.component('child', ChildComponent); 


    <div ng-app="app"><parent></parent></div> 

вещи, которые я сделал в этом примере кода:

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

  2. Удалено Требовать определение дочернего компонента, поскольку он будет зависеть от вашего дочернего компонента от родительского компонента. существует другой вариант использования, когда вы должны использовать родителя. лучше всего использовать привязки и $ onChanges для обновления данных у ребенка от родителя,

  3. добавил некоторые подтверждения к данным $ onChanges.

    если (changesObj.hasOwnProperty ('значение')) { this.value = changesObj.value.currentValue }

вы должны понимать, что изменение OBJ простое изменение объекта. он имеет несколько свойств, таких как first change(), текущее значение, OldValue и т. д. вы всегда должны проверять, что вы хотите отсюда. также я устанавливаю его в this.value, который является текущим объемом. мы не используем непосредственную область действия родительской области или переменной области привязки. Я создаю новый объект области, который вы будете использовать для отображения данных. он будет заселен объектом привязки.

в целом это происходит 1.parent interval обновляет родитель объем

2. this.value передается ребенку, как крепления

3. $onChanges проверяет привязки и присваивает его локальную область видимости this.value

4.child шаблон this.value в UI

Смежные вопросы