Quiero usar un controlador de 2 separados de los elementos HTML, y el uso de la $rootScope para mantener las 2 listas en la sincronización cuando uno es editado:

HTML

<ul class="nav" ng-controller="Menu">
    <li ng-repeat="item in menu">
        <a href="{{item.href}}">{{item.title}}</a>
    </li>
</ul>

<div ng-controller="Menu">
    <input type="text" id="newItem" value="" />
    <input type="submit" ng-click="addItem()" />
    <ul class="nav" ng-controller="Menu">
        <li ng-repeat="item in menu">
            <a href="{{item.href}}">{{item.title}}</a>
        </li>
    </ul>    
</div>

JS

angular.module('menuApp', ['menuServices']).
    run(function($rootScope){
        $rootScope.menu = [];
    });

angular.module('menuServices', ['ngResource']).
    factory('MenuData', function ($resource) {
        return $resource(
            '/tool/menu.cfc', 
            {
                returnFormat: 'json'
            },
            {
                getMenu: {
                    method: 'GET',
                    params: {method: 'getMenu'}
                },
                addItem: {
                    method: 'GET',
                    params: {method: 'addItem'}
                }
            }
        );
    });

function Menu($scope, MenuData) {

    //attempt to add new item
    $scope.addNewItem = function(){
        var thisItem = $('#newItem').val();

        MenuData.addItem({item: thisItem},function(data){
            $scope.updateMenu();
        });
    }   

    $scope.updateMenu = function() {
        MenuData.getMenu({},function(data){
            $scope.menu = data.MENU;
        });         
    }

    //get menu data
    $scope.updateMenu();
}

Cuando se carga la página, tanto en el UL y la DIV mostrar el contenido correcto de la base de datos, pero cuando uso el addNewItem() método sólo el DIV se actualiza.

Hay una manera mejor a la estructura de mi lógica, o puedo hacer algo para asegurarse de que el $scope.menu en el UL se actualizan al mismo tiempo?

He aquí un ejemplo de algo similar: http://plnkr.co/edit/2a55gq

  • Usted podría tener el menú en un servicio junto con los métodos para actualizar el menú de sí mismo, y tener el servicio de difusión de la actualización del menú a través de $rootScope.$la emisión. Los controladores tienen escuchar el evento con $scope.$y actualización de la configuración regional de referencia para el menú a través de $scope.menú = …
  • He actualizado mi respuesta en caso de que quiera saber cómo hacerlo en la directiva.
  • Esta respuesta incluye un muy interesante vídeo así: stackoverflow.com/a/13882619/109941
InformationsquelleAutor Pete | 2012-11-01

3 Comentarios

  1. 43

    Yo sugiero utilizar un servicio que contiene el menú y sus métodos. El servicio de actualización en el menú que se hace referencia por el controlador(s).

    Ver un trabajo plunker aquí: http://plnkr.co/edit/Bzjruq

    Este es el ejemplo de código JavaScript:

    angular
     .module( 'sampleApp', [] )
     .service( 'MenuService', [ '$rootScope', function( $rootScope ) {
    
       return {
          menu: [ 'item 1' ],
          add: function( item ) {
            this.menu.push( item );
          } 
       };
    
     }])
     .controller( 'ControllerA', [ 'MenuService', '$scope', function( MenuService, $scope ) {
    
       $scope.menu = MenuService.menu;
    
       $scope.addItem = function() {
        MenuService.add( $scope.newItem );  
       };
    
     }]);

    Y la página Html de ejemplo:

    <!DOCTYPE html>
    <html>
    
      <head lang="en">
        <meta charset="utf-8">
        <title>Custom Plunker</title>
        <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.min.js"></script>
        <script src="app.js"></script>
      </head>
    
      <body ng-app="sampleApp">
    
        <div ng-controller="ControllerA">
          <ul>
            <li ng-repeat="item in menu">{{item}}</li>
          </ul>
          <input type="text" ng-model="newItem" /><input type="submit" ng-click="addItem()" />
        </div>
    
        <div ng-controller="ControllerA">
          <ul>
            <li ng-repeat="item in menu">{{item}}</li>
          </ul>
        </div>
    
      </body>
    
    </html>
    • Esa es la cosa, acabo de mirar en esto después de publicado ese comentario, gracias!
    • No $scope.menu se actualizará automáticamente cuando MenuSerice.add se llama, incluso sin la $rootScope.$broadcast y $scope.$on cosas? Desde $scope.menu apunta directamente a MenuService.menu, no es una copia de la misma.
    • gracias, he actualizado la respuesta y los relacionados con la Plunker.
    • Por lo tanto, es una muy mala práctica para adjuntar un mismo controlador a la vista de muchos elementos? O hay momentos durante el desarrollo, que tal solución es aceptable? Veo que no hay errores en webdev herramientas de la consola, cuando se ejecuta webapp que tiene sucio hack (?).
  2. 5

    Edición:

    Aquí está la versión actualizada plunker. funciona en dos controlador.

    Idea principal es utilizar un servicio de difusión y sincronizar los datos con la directiva.

    app.service('syncSRV', function ($rootScope) {
    "use strict";
    this.sync = function (data) {
    this.syncData = data;
    $rootScope.$broadcast('updated');
    };
    });
    app.controller('MainCtrl1', ['$scope', function ($scope) {
    }])
    .controller('MainCtrl2', ['$scope', function ($scope) {
    }]);
    app.directive('sync',function (syncSRV) {
    "use strict";
    return {
    template: '<div><input ng-model="syncdata" type="text" /></div> ',
    controller: function ($scope, $element, $attrs) {
    $scope.$watch('syncdata', function (newVal, oldVal, $scope) {
    syncSRV.sync(newVal);
    }, true);
    }
    };
    }).directive('dataview', function (syncSRV) {
    "use strict";
    return {
    template: '<div>Sync data : {{data}}</div> ',
    controller: function ($scope, $element, $attrs) {
    $scope.$on('updated', function () {
    $scope.data = syncSRV.syncData;
    });
    }
    };
    });
    <div ng-controller="MainCtrl1">
    <fieldset>
    <legend> Controller 1</legend>
    <div dataview></div>
    <div sync></div>
    </fieldset>
    </div>
    <div ng-controller="MainCtrl2">
    <fieldset>
    <legend> Controller 2</legend>
    <div dataview></div>
    <div sync></div>
    </fieldset>
    </div>

    Aquí es lo que yo haría para este caso.

    Voy a crear una directiva para

    <ul class="nav" ng-controller="Menu">
    <li ng-repeat="item in menu">
    <a href="{{item.href}}">{{item.title}}</a>
    </li>
    </ul> 

    así que una vez que el elemento se actualiza, se actualizará en la directiva.

    pequeño ejemplo

    • Su ejemplo sólo tiene 1 controlador, tendría que todavía funcionan a través de 2 diferentes controladores? por ejemplo: plnkr.co/editar/2a55gq. Yo estoy limitado en ¿cómo puedo modificar mi página HTML
  3. 1

    Sólo quiero actualizar y simplificar la respuesta seleccionada. Parece que puede reducir mediante la supresión de esta línea:
    $rootScope.$broadcast( 'MenuService.update', this.menu );

    y este fragmento:

    $scope.$on( 'MenuService.update', function( event, menu ) {
    $scope.menu = menu;
    });

    La razón de ser, ya estamos utilizando un Servicio, y que básicamente une los dos controladores idénticos, así que no hay necesidad de usar $rootScope.$difusión y agregar un observable.

    De trabajo plunk aquí:
    http://plnkr.co/edit/1efEwU?p=preview

    Sólo necesitas enlazar el servicio, cuando me refactorizar el código que fue capaz de reducir a 13 líneas en lugar de 22.

Dejar respuesta

Please enter your comment!
Please enter your name here