restrict - how to use scope angularjs




Como passar dados entre componentes irmãos sem usar $ scope? (2)

Abordagem de componentes

Eu sugiro que você se alinhe com a abordagem do componente Angular 2 e use a abordagem de inputs / outputs . Se você fizer isso, poderá migrar facilmente para o Angular 2, porque os componentes serão conceitualmente idênticos (com diferença apenas na sintaxe). Então aqui está o jeito que você faz.

Então, basicamente queremos que o cabeçalho e os componentes principais compartilhem parte do estado com o cabeçalho para poder alterá-lo. Existem várias abordagens que podemos usar para fazê-lo funcionar, mas a mais simples é fazer uso da propriedade intermediária do controlador pai. Então, vamos assumir que o controlador pai (ou componente) define essa propriedade de view você deseja que seja usada pelos componentes de cabeçalho (pode ler e modificar) e principal (pode ler).

Componente de cabeçalho : entrada e saída.

Aqui está como um componente de cabeçalho simples pode parecer:

.component('headerComponent', {
  template: `
    <h3>Header component</h3>
    <a ng-class="{'btn-primary': $ctrl.view === 'list'}" ng-click="$ctrl.setView('list')">List</a>
    <a ng-class="{'btn-primary': $ctrl.view === 'table'}" ng-click="$ctrl.setView('table')">Table</a>
  `,
  controller: function() {
    this.setView = function(view) {
      this.view = view
      this.onViewChange({$event: {view: view}})
    }
  },
  bindings: {
    view: '<',
    onViewChange: '&'
  }
})

A parte mais importante aqui são as ligações. Com view: '<' , especificamos que o componente do header será capaz de ler algo externo e vinculá-lo como propriedade de view do próprio controlador. Com onViewChange: '&' componentes onViewChange: '&' saídas definidas: o canal para notificar / atualizar o mundo exterior com o que for necessário. O componente do cabeçalho enviará alguns dados por esse canal, mas não sabe o que o componente pai fará com ele e não deve se importar.

Isso significa que o controlador de header pode ser usado como

<header-component view="root.view" on-view-change="root.view = $event.view"></header-component> 

Componente principal : entrada.

O componente principal é mais simples, basta definir as entradas que aceita:

.component('mainComponent', {
  template: `
    <h4>Main component</h4>
    Main view: {{ $ctrl.view }}
  `,
  bindings: {
    view: '<'
  }
})

Vista principal

E, finalmente, tudo conectado:

<header-component view="root.view" on-view-change="root.view = $event.view"></header-component>
<main-component view="root.view"></main-component>

Dê uma olhada e jogue com uma demonstração simples.

angular.module('demo', [])

.controller('RootController', function() {
  this.view = 'table'
})

.component('headerComponent', {
  template: `
    <h3>Header component</h3>
    <a class="btn btn-default btn-sm" ng-class="{'btn-primary': $ctrl.view === 'list'}" ng-click="$ctrl.setView('list')">List</a>
    <a class="btn btn-default btn-sm" ng-class="{'btn-primary': $ctrl.view === 'table'}" ng-click="$ctrl.setView('table')">Table</a>
  `,
  controller: function() {
    this.setView = function(view) {
      this.view = view
      this.onViewChange({$event: {view: view}})
    }
  },
  bindings: {
    view: '<',
    onViewChange: '&'
  }
})

.component('mainComponent', {
  template: `
    <h4>Main component</h4>
    Main view: {{ $ctrl.view }}
  `,
  bindings: {
    view: '<'
  }
})
<script src="https://code.angularjs.org/1.5.0/angular.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.css" />

<div class="container" ng-app="demo" ng-controller="RootController as root">
  
    <pre>Root view: {{ root.view }}</pre>
    
    <header-component view="root.view" on-view-change="root.view = $event.view"></header-component>
    <main-component view="root.view"></main-component>
    
</div>

Demo: http://plnkr.co/edit/ODuY5Mp9HhbqA31G4w3t?p=info

Aqui está um post que escrevi sobre o design baseado em componentes em detalhes: http://dfsq.info/site/read/angular-components-communication

Estou criando um componente que contém três componentes filhos desta maneira:

<header-component>
<side-component>
<main-component>

O componente principal contém uma lista de heróis. O componente do cabeçalho contém dois botões que devem mudar a exibição no componente principal para exibição de lista ou grade.

O problema que tenho agora é passar dados do componente de cabeçalho para o componente principal. Portanto, quando eu clico no botão de grade, a exibição no conteúdo principal deve mudar para exibição em grade, o mesmo para a exibição em linha.

Como os dados podem ser passados ​​entre componentes filhos na angular 1.5?


Embora a abordagem do componente pai (transmitir dados por meio de atributos) seja uma perfeita implementação válida e boa, podemos conseguir a mesma coisa de uma maneira mais simples usando uma fábrica de lojas .

Basicamente, os dados são mantidos pelo Store , que é referenciado no escopo de ambos os componentes, permitindo atualizações reativas da interface do usuário quando o estado é alterado.

Exemplo:

angular
    .module('YourApp')
    // declare the "Store" or whatever name that make sense
    // for you to call it (Model, State, etc.)
    .factory('Store', () => {
        // hold a local copy of the state, setting its defaults
        const state = {
            data: {
              heroes: [],
              viewType: 'grid'
            }
        };
        // expose basic getter and setter methods
        return {
            get() {
                return state.data;
            },
            set(data) {
                Object.assign(state.data, data);
            },
        };
    });

Em seus componentes, você deve ter algo como:

angular
    .module('YourApp')
    .component('headerComponent', {
        // inject the Store dependency
        controller(Store) {
            // get the store reference and bind it to the scope:
            // now, every change made to the store data will
            // automatically update your component UI
            this.state = Store.get();

            // ... your code
        },
        template: `
            <div ng-show="$ctrl.state.viewType === 'grid'">...</div>
            <div ng-show="$ctrl.state.viewType === 'row'">...</div>
            ...
        `
    })
    .component('mainComponent', {
        // same here, we need to inject the Store
        controller(Store) {
            // callback for the switch view button
            this.switchViewType = (type) => {
                // change the Store data:
                // no need to notify or anything
                Store.set({ viewType: type });
            };

            // ... your code
        },
        template: `
            <button ng-click="$ctrl.switchViewType('grid')">Switch to grid</button>
            <button ng-click="$ctrl.switchViewType('row')">Switch to row</button>
            ...
        `

Se você quiser ver um exemplo de trabalho, confira este CodePen .

Fazendo isso, você também pode ativar a comunicação entre 2 ou N componentes . Você só precisa:

  1. injetar a dependência da loja
  2. certifique-se de vincular os dados da loja ao seu escopo do componente

como no exemplo acima ( <header-component> ).

No mundo real, um aplicativo típico precisa gerenciar muitos dados, portanto, faz mais sentido dividir logicamente os domínios de dados de alguma forma. Seguindo a mesma abordagem, você pode adicionar mais fábricas da loja . Por exemplo, para gerenciar as informações atuais do usuário registradas e um recurso externo (por exemplo, catálogo), você pode criar uma UserStore mais uma CatalogStore - alternativamente, CatalogModel e CatalogModel ; essas entidades também seriam bons lugares para centralizar coisas como comunicação com o back-end, adicionar lógica de negócios personalizada, etc. O gerenciamento de dados será de responsabilidade exclusiva das fábricas da Store .

Lembre-se de que estamos modificando os dados da loja . Embora essa abordagem seja simples e clara, ela pode não ser bem dimensionada porque produzirá efeitos colaterais . Se você deseja algo mais avançado (imutabilidade, funções puras, árvore de estado único, etc.), verifique Redux , ou se finalmente quiser mudar para o Angular 2, dê uma olhada no ngrx/store .

Espero que isto ajude! :)

Você não precisa fazer isso da maneira Angular 2, porque no caso de migrar algumas vezes ... Faça isso se fizer sentido.





angularjs-controlleras