Failed to communicate child driver with its parent driver

3

I am creating my first application with AngularJS, and I have an error that I have not found a solution for. The problem is that at the moment of generating the values in the form, the table does not show them.

This is the html code:

<!DOCTYPE html>
<html ng-app="appRegistro">
<head>
<meta charset="UTF-8"> 
<title>App de Prueba</title>
<script type="text/javascript" src="js/angular.js"></script>
<script type="text/javascript" src="js/app.js"></script>
<link rel="stylesheet" type="text/css" href="css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="css/estilos.css">
</head>
<body ng-controller="ControladorAplicacion as cntrl">
<div id="cuerpo" class="row">
    <div class="col-md-4 col-lg-4">
        <h3>App de Prueba</h3>
        <!--Seccion de la app que acepta la informacion del votante-->
        <form name="forma_datos" ng-controller="ControladorRegistro as reg" ng-submit="reg.agregarRegistro(votante)">
            <p>Cedula: <input ng-model="reg.registro.cedula" type="text" ></input></p>
            <p>Telefono: <input ng-model="reg.registro.telefono" type="text"></input></p>
            <p>Nombre Completo: <input ng-model="reg.registro.nombre" type="text"></input></p>
            <p>Municipio: <input ng-model="reg.registro.municipio" type="text"></input></p>
            <p>Parroquia: <input ng-model="reg.registro.parroquia" type="text"></input></p>
            <p>Centro: <input ng-model="reg.registro.centro" type="text"></p>
            <button type="button submit" class="btn btn-primary" ng-click="expression">Agregar</button>
        </form>
        <br/>
        <br/>
        <!--Tabla para la presentacion de valores ingresados-->
        <table>
            <tr>
                <td>Cedula</td>
                <td>Nombre Completo</td>
                <td>Telefono</td>
                <td>Municipio</td>
                <td>Parroquia</td>
                <td>Centro</td>
            </tr>
            <tr ng-repeat="registro in cntrl.registros">
                <td>{{reg.registro.cedula}}</td>
                <td>{{reg.registro.nombre}}</td>
                <td>{{reg.registro.telefono}}</td>
                <td>{{reg.registro.municipio}}</td>
                <td>{{reg.registro.parroquia}}</td>
                <td>{{reg.registro.centro}}</td>
            </tr>
        </table>
    </div>
</div>
</body>
</html>

And this is the controller:

(function(){
//Inicializador de la aplicacion
var app = angular.module('appRegistro', []);

//Inicializador del controlador
app.controller('ControladorAplicacion', function(){
    this.registros = regs;
});

//Controlador para la función
app.controller('ControladorRegistro', function(){
    this.registro = {};

    this.agregarRegistro = function(votante){
        votante.registros.push(this.registro);
        this.registro = {};         
    };
});

var regs = [{
    cedula : '10111000',
    nombre : 'Luis Lopez',
    telefono : '04141230011'
}];

})();

Thanks in advance

    
asked by AJParejo 12.05.2016 в 09:35
source

2 answers

1

You have two controllers, one inside another. Your problem is that you have to communicate two $scope different (from child to parent) and generally the way to do this one of the following

  • In the child controller injecting $ scope and navigating to the parent with the property $parent .
  • In the view, using a expression and referencing the desired value in the parent.
  • Using $ emit from the child controller to send the data to your parent using a event
  • Solution 1

    In the controller it would be something like this

    app.controller('ControladorRegistro', function ($scope) {
        var vm = this;
        vm.registro = {};
    
        vm.agregarRegistro = function () {
            // cntrl es el mismo valor que especificaste en controllerAs
            $scope.$parent.cntrl.registros.push(vm.registro);
            vm.registro = {};
        };
    });
    

    (function() {
      //Inicializador de la aplicacion
      var app = angular.module('appRegistro', []);
    
      //Inicializador del controlador
      app.controller('ControladorAplicacion', function() {
        var cntrl = this;
        cntrl.registros = regs;
      });
    
      //Controlador para la función
      app.controller('ControladorRegistro', function($scope) {
        var reg = this;
        reg.registro = {};
    
        reg.agregarRegistro = function() {
          // cntrl es el mismo valor que especificaste en controllerAs
          $scope.$parent.cntrl.registros.push(reg.registro);
          reg.registro = {};
        };
      });
    
      var regs = [{
        cedula: '10111000',
        nombre: 'Luis Lopez',
        telefono: '04141230011'
      }];
    
    })();
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
    <div ng-app="appRegistro" ng-controller="ControladorAplicacion as cntrl">
      <div id="cuerpo" class="row">
        <div class="col-md-4 col-lg-4">
          <h3>App de Prueba</h3>
          <!--Seccion de la app que acepta la informacion del votante-->
          <form name="forma_datos" ng-controller="ControladorRegistro as reg" ng-submit="reg.agregarRegistro()">
            <label>Cedula:</label>
            <input class="form-control" ng-model="reg.registro.cedula" type="text">
            <label>Telefono:</label>
            <input class="form-control" ng-model="reg.registro.telefono" type="text">
            <label>Nombre Completo:</label>
            <input class="form-control" ng-model="reg.registro.nombre" type="text">
            <label>Municipio:</label>
            <input class="form-control" ng-model="reg.registro.municipio" type="text">
            <label>Parroquia:</label>
            <input class="form-control" ng-model="reg.registro.parroquia" type="text">
            <label>Centro:</label>
            <input class="form-control" ng-model="reg.registro.centro" type="text">
            <button type="submit" class="btn btn-primary">Agregar</button>
          </form>
          <br/>
          <br/>
        </div>
      </div>
      <!--Tabla para la presentacion de valores ingresados-->
      <table class="table table-responsive">
        <tr>
          <td>Cedula</td>
          <td>Nombre Completo</td>
          <td>Telefono</td>
          <td>Municipio</td>
          <td>Parroquia</td>
          <td>Centro</td>
        </tr>
        <tr ng-repeat="registro in cntrl.registros">
          <td>{{registro.cedula}}</td>
          <td>{{registro.nombre}}</td>
          <td>{{registro.telefono}}</td>
          <td>{{registro.municipio}}</td>
          <td>{{registro.parroquia}}</td>
          <td>{{registro.centro}}</td>
        </tr>
      </table>
    </div>

    I really do not like this way. Just look at the expression $scope.$parent.cntrl.registros so you can see how hard to maintain it will be when you have to use it frequently.

    Solution 2

    You can pass the correct value from the view since here you can directly reference the parent controller

    <form name="forma_datos" ng-controller="ControladorRegistro as reg" 
        ng-submit="reg.agregarRegistro(cntrl.registros)">
        <!-- Usas la variable cntrl para referenciar el controller correcto -->
        <!-- Resto de los campos -->
    </form>
    

    Then in controller it would be

    vm.agregarRegistro = function (registros) {
        // La referencia correcta nos llega como un parámetro de la funcion
        registros.push(vm.registro);
        vm.registro = {};
    };
    

    (function() {
      //Inicializador de la aplicacion
      var app = angular.module('appRegistro', []);
    
      //Inicializador del controlador
      app.controller('ControladorAplicacion', function() {
        var cntrl = this;
        cntrl.registros = regs;
      });
    
      //Controlador para la función
      app.controller('ControladorRegistro', function() {
        var reg = this;
        reg.registro = {};
    
        reg.agregarRegistro = function(registros) {
          // se obtiene la referencia correcta por parámetros
          registros.push(reg.registro);
          reg.registro = {};
        };
      });
    
      var regs = [{
        cedula: '10111000',
        nombre: 'Luis Lopez',
        telefono: '04141230011'
      }];
    
    })();
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
    <div ng-app="appRegistro" ng-controller="ControladorAplicacion as cntrl">
      <div id="cuerpo" class="row">
        <div class="col-md-4 col-lg-4">
          <h3>App de Prueba</h3>
          <!--Seccion de la app que acepta la informacion del votante-->
          <form name="forma_datos" ng-controller="ControladorRegistro as reg" ng-submit="reg.agregarRegistro(cntrl.registros)">
            <label>Cedula:</label>
            <input class="form-control" ng-model="reg.registro.cedula" type="text">
            <label>Telefono:</label>
            <input class="form-control" ng-model="reg.registro.telefono" type="text">
            <label>Nombre Completo:</label>
            <input class="form-control" ng-model="reg.registro.nombre" type="text">
            <label>Municipio:</label>
            <input class="form-control" ng-model="reg.registro.municipio" type="text">
            <label>Parroquia:</label>
            <input class="form-control" ng-model="reg.registro.parroquia" type="text">
            <label>Centro:</label>
            <input class="form-control" ng-model="reg.registro.centro" type="text">
            <button type="submit" class="btn btn-primary">Agregar</button>
          </form>
          <br/>
          <br/>
        </div>
      </div>
      <!--Tabla para la presentacion de valores ingresados-->
      <table class="table table-responsive">
        <tr>
          <td>Cedula</td>
          <td>Nombre Completo</td>
          <td>Telefono</td>
          <td>Municipio</td>
          <td>Parroquia</td>
          <td>Centro</td>
        </tr>
        <tr ng-repeat="registro in cntrl.registros">
          <td>{{registro.cedula}}</td>
          <td>{{registro.nombre}}</td>
          <td>{{registro.telefono}}</td>
          <td>{{registro.municipio}}</td>
          <td>{{registro.parroquia}}</td>
          <td>{{registro.centro}}</td>
        </tr>
      </table>
    </div>

    Solution 3

    This is in my opinion the most recommended when trying child-parent communication as it may happen that in the future you insert a controller in the middle and other solutions present problems.

    app.controller('ControladorRegistro', function($scope){
        var vm = this;
        vm.registro = {};
    
        vm.agregarRegistro = function() {
            // Se emite el evento al presionar el boton
            $scope.$emit('nuevo_registro', vm.registro);
            vm.registro = {};         
        };
    });
    
    app.controller('ControladorAplicacion', function($scope){
        var vm = this;
        vm.registros = regs;
    
        // En caso que se reciba el evento insertamos el nuevo registro
        $scope.$on('nuevo_registro', function(evt, nuevo) {
            vm.registros.push(nuevo);
        })
    });
    

    (function() {
      //Inicializador de la aplicacion
      var app = angular.module('appRegistro', []);
    
      //Inicializador del controlador
    
      app.controller('ControladorAplicacion', function($scope) {
        var cntrl = this;
        cntrl.registros = regs;
    
        // En caso que se reciba el evento insertamos el nuevo registro
        $scope.$on('nuevo_registro', function(evt, nuevo) {
          cntrl.registros.push(nuevo);
        })
      });
    
      //Controlador para la función
      app.controller('ControladorRegistro', function($scope) {
        var reg = this;
        reg.registro = {};
    
        reg.agregarRegistro = function() {
          // Se emite el evento al presionar el boton
          $scope.$emit('nuevo_registro', reg.registro);
          reg.registro = {};
        };
      });
    
      var regs = [{
        cedula: '10111000',
        nombre: 'Luis Lopez',
        telefono: '04141230011'
      }];
    
    })();
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
    <div ng-app="appRegistro" ng-controller="ControladorAplicacion as cntrl">
      <div id="cuerpo" class="row">
        <div class="col-md-4 col-lg-4">
          <h3>App de Prueba</h3>
          <!--Seccion de la app que acepta la informacion del votante-->
          <form name="forma_datos" ng-controller="ControladorRegistro as reg" ng-submit="reg.agregarRegistro()">
            <label>Cedula:</label>
            <input class="form-control" ng-model="reg.registro.cedula" type="text">
            <label>Telefono:</label>
            <input class="form-control" ng-model="reg.registro.telefono" type="text">
            <label>Nombre Completo:</label>
            <input class="form-control" ng-model="reg.registro.nombre" type="text">
            <label>Municipio:</label>
            <input class="form-control" ng-model="reg.registro.municipio" type="text">
            <label>Parroquia:</label>
            <input class="form-control" ng-model="reg.registro.parroquia" type="text">
            <label>Centro:</label>
            <input class="form-control" ng-model="reg.registro.centro" type="text">
            <button type="submit" class="btn btn-primary">Agregar</button>
          </form>
          <br/>
          <br/>
        </div>
      </div>
      <!--Tabla para la presentacion de valores ingresados-->
      <table class="table table-responsive">
        <tr>
          <td>Cedula</td>
          <td>Nombre Completo</td>
          <td>Telefono</td>
          <td>Municipio</td>
          <td>Parroquia</td>
          <td>Centro</td>
        </tr>
        <tr ng-repeat="registro in cntrl.registros">
          <td>{{registro.cedula}}</td>
          <td>{{registro.nombre}}</td>
          <td>{{registro.telefono}}</td>
          <td>{{registro.municipio}}</td>
          <td>{{registro.parroquia}}</td>
          <td>{{registro.centro}}</td>
        </tr>
      </table>
    </div>

    Finally, as a personal note, I corrected some mistakes that I mention below.

    • Do not use <input></input> , this is illegal. The correct form is <input /> or just <input> in html5
    • If you are using bootstrap use the classes of forms and tables to improve the appearance of your interface
    • Do not use this only on your controllers. You can easily lose this reference in events and other places. Assign it to a variable, eg vm , or the name you put in controllerAs and use the variable directly.
    • The ng-repeat directive creates a variable and a new $scope in each iteration. Use that variable to reference the data or you will have to navigate to the parent (controller "ControllerRegister") using $parent . Instead of {{reg.registro.cedula}} is {{registro.cedula}}
    answered by 12.05.2016 / 18:33
    source
    0

    The problem seems to be in your way of calling objects through ngRepeat . A ngRepeat is telling you to iterate over the cntrl.registros object (which I'm seeing, I'm not sure you've created it) by returning the values under the name of "record". Here, the correct way to show them is not to call reg.registro.<campo> , but to registro.<campo>

    <tr ng-repeat="registro in cntrl.registros">
      <td>{{registro.cedula}}</td>
      <td>{{registro.nombre}}</td>
      <td>{{registro.telefono}}</td>
      <td>{{registro.municipio}}</td>
      <td>{{registro.parroquia}}</td>
      <td>{{registro.centro}}</td>
    </tr>
    

    I recommend you take a look at ngRepeat and make sure you are creating the object correctly in your driver.

    Greetings.

        
    answered by 12.05.2016 в 18:11