¿Cómo pasar parámetros a un modal?


96

Quiero pasar el userNamede una lista de userNamelos clics de un usuario que ha iniciado sesión a twitter bootstrap modal. Estoy usando griales con AngularJS , donde los datos se hace a través de AngularJS .

Configuración

Mi página de vista de griales encouragement.gspes

<div ng-controller="EncouragementController">
    <g:render template="encourage/encouragement_modal" />
    <tr ng-cloak
                  ng-repeat="user in result.users">
                   <td>{{user.userName}}</rd>
                   <td>
                      <a class="btn btn-primary span11" href="#encouragementModal" data-toggle="modal">
                            Encourage
                       </a>
                  </td>
                </tr>

Mi encourage/_encouragement_modal.gspes

<div id="encouragementModal" class="modal hide fade">
  <div class="modal-header">
    <button type="button" class="close" data-dismiss="modal"
      aria-hidden="true">&times;</button>
    <h3>Confirm encouragement?</h3>
  </div>
  <div class="modal-body">
      Do you really want to encourage <b>{{aModel.userName}}</b>?
  </div>
  <div class="modal-footer">
    <button class="btn btn-info"
      ng-click="encourage('${createLink(uri: '/encourage/')}',{{aModel.userName}})">
      Confirm
    </button>
    <button class="btn" data-dismiss="modal" aria-hidden="true">Never Mind</button>
  </div>
</div>

Entonces, ¿cómo puedo pasar userNamea encouragementModal?


1
Debes manejar estas cosas usando angularjs. checkout ng-include.
zs2020

Respuestas:


149

Para pasar el parámetro, debe usar resolver e inyectar los elementos en el controlador

$scope.Edit = function (Id) {
   var modalInstance = $modal.open({
      templateUrl: '/app/views/admin/addeditphone.html',
      controller: 'EditCtrl',
      resolve: {
         editId: function () {
           return Id;
         }
       }
    });
}

Ahora, si va a usar así:

app.controller('EditCtrl', ['$scope', '$location'
       , function ($scope, $location, editId)

en este caso, editId no estará definido. Necesitas inyectarlo, así:

app.controller('EditCtrl', ['$scope', '$location', 'editId'
     , function ($scope, $location, editId)

Ahora funcionará sin problemas, me enfrento al mismo problema muchas veces, una vez inyectado, ¡todo comienza a funcionar!


Como todo Angular, la inyección es la solución. ¡Gracias!
Sebastialonso

¡Este error indefinido me estaba metiendo la cabeza hasta que vi tu respuesta! ¡Funciona de maravilla!
Dan

¿Cómo se hace si en lugar de una var simplemente desea pasar algún objeto de tiempo de espera? la resolución no se activará hasta que se haya resuelto el tiempo de espera, lo que ocurre al final del tiempo de espera
Danny22

Lo que me faltaba en mi solución era usar $ scope y $ location entre comillas simples ... No sabía que esos argumentos tenían que ser cadenas
rshimoda

1
Al hacer esto, obtengo "angular.js: 10071 Error: [$ injector: unpr] Proveedor desconocido: editIdProvider <- editId". ¿Algunas ideas?
Oskar Lund

57

El otro no funciona. Según los documentos, esta es la forma en que debe hacerlo.

angular.module('plunker', ['ui.bootstrap']);
var ModalDemoCtrl = function ($scope, $modal) {

    var modalInstance = $modal.open({
      templateUrl: 'myModalContent.html',
      controller: ModalInstanceCtrl,
      resolve: {
        test: function () {
          return 'test variable';
        }
      }
    });
};

var ModalInstanceCtrl = function ($scope, $modalInstance, test) {

  $scope.test = test;
};

Ver plunkr


1
¿No debería ajustar esto como ['$ scope', '$ modalInstance', function () para inyectar dependencias?
joseramonc

1
Gracias por el comentario, José, ese fue exactamente mi problema. Si está minimizando su código angular, sí, debe usar la sintaxis de matriz para ModalInstanceCtrl.
mcole

José, +1 También fue mi problema. ¡Y pienso en todos que usan AngularUI!
Matteo Defanti

50

Alternativamente, puede crear un nuevo alcance y pasar parámetros a través de la opción de alcance

var scope = $rootScope.$new();
 scope.params = {editId: $scope.editId};
    $modal.open({
        scope: scope,
        templateUrl: 'template.html',
        controller: 'Controller',
    });

En su controlador modal, pase $ scope, entonces no necesita pasar y itemsProvider o lo que sea que lo haya llamado

modalController = function($scope) {
    console.log($scope.params)
}

2
$ rootScope. $ nuevo (); <=== esto debería ser votado a favor. truco muy limpio. ¡Gracias!
Reflog

3
+1 Dado que esto permite pasar datos sin tener que definir un controlador para el modal. Por cierto, puede hacer $scope.$new(true)para crear un nuevo alcance aislado sin la necesidad de inyectar $rootScope.
Santosh

@Mwayi: ¡Gracias por este consejo! El problema con la inyección clásica (uso resolve) es que los argumentos son obligatorios, por lo que cada vez que abre un modal, debe resolver todos los argumentos o la llamada a $modal.open()fallará porque el controlador quiere sus argumentos. Al usar este ingenioso scopetruco, las dependencias se vuelven opcionales.
stackular

23

También puede pasar parámetros fácilmente al controlador modal agregando una nueva propiedad con una instancia de modal y llevarla al controlador modal. Por ejemplo:

A continuación se muestra mi evento de clic en el que quiero abrir la vista modal.

 $scope.openMyModalView = function() {
            var modalInstance = $modal.open({
                    templateUrl: 'app/userDetailView.html',
                    controller: 'UserDetailCtrl as userDetail'
                });
                // add your parameter with modal instance
                modalInstance.userName = 'xyz';
        };

Controlador modal:

angular.module('myApp').controller('UserDetailCtrl', ['$modalInstance',
                function ($modalInstance) {
                    // get your parameter from modal instance
                    var currentUser = $modalInstance.userName;
                    // do your work...
                }]);

Exactamente lo que necesitaba. Funcionó perfectamente.
theFish

17

Intenté lo siguiente.

Llamé ng-clickal controlador de angularjs en el botón Animar ,

               <tr ng-cloak
                  ng-repeat="user in result.users">
                   <td>{{user.userName}}</rd>
                   <td>
                      <a class="btn btn-primary span11" ng-click="setUsername({{user.userName}})" href="#encouragementModal" data-toggle="modal">
                            Encourage
                       </a>
                  </td>
                </tr>

Puse userNamede encouragementModaldesde AngularJS controlador.

    /**
     * Encouragement controller for AngularJS
     * 
     * @param $scope
     * @param $http
     * @param encouragementService
     */
    function EncouragementController($scope, $http, encouragementService) {
      /**
       * set invoice number
       */
      $scope.setUsername = function (username) {
            $scope.userName = username;
      };
     }
    EncouragementController.$inject = [ '$scope', '$http', 'encouragementService' ];

Proporcioné un lugar ( userName) para obtener el valor del controlador angularjs encouragementModal.

<div id="encouragementModal" class="modal hide fade">
  <div class="modal-header">
    <button type="button" class="close" data-dismiss="modal"
      aria-hidden="true">&times;</button>
    <h3>Confirm encouragement?</h3>
  </div>
  <div class="modal-body">
      Do you really want to encourage <b>{{userName}}</b>?
  </div>
  <div class="modal-footer">
    <button class="btn btn-info"
      ng-click="encourage('${createLink(uri: '/encourage/')}',{{userName}})">
      Confirm
    </button>
    <button class="btn" data-dismiss="modal" aria-hidden="true">Never Mind</button>
  </div>
</div>

Funcionó y me saludé.


3
Yo +1 y te saludo. Si alguien necesita pasar todo el usuario al modal en lugar de una sola cadena para su nombre, en el controlador, recuerde usar angular.copy(user).
youri

10

Realmente deberías usar Angular UI para esas necesidades. Échale un vistazo: Diálogo de interfaz de usuario angular

En pocas palabras, con el diálogo de interfaz de usuario angular, puede pasar una variable de un controlador al controlador de diálogo usando resolve. Aquí está su controlador "de":

var d = $dialog.dialog({
  backdrop: true,
  keyboard: true,
  backdropClick: true,
  templateUrl:  '<url_of_your_template>',
  controller: 'MyDialogCtrl',
  // Interesting stuff here.
  resolve: {
    username: 'foo'
  }
});

d.open();

Y en su controlador de diálogo:

angular.module('mymodule')
  .controller('MyDialogCtrl', function ($scope, username) {
  // Here, username is 'foo'
  $scope.username = username;
}

EDITAR: Desde la nueva versión del ui-dialog, la entrada de resolución se convierte en:

resolve: { username: function () { return 'foo'; } }


Hola, no lo intenté de esta manera. Pero +1 por una sugerencia.
prayagupd

3
en realidad debería serresolve: function(){return {username: 'foo'}}
SET

La respuesta de SET no funcionará. bicicleta lo tiene justo debajo, debería ser- resolver: {data: function () {return 'foo';}}
bornytm

1
@bornytm Hoy en día tienes razón. Pero cuando escribí mi respuesta, la sintaxis era:resolve: { username: 'foo'}
Sandro Munda

4

Simplemente puede crear una función de controlador y pasar sus parámetros con el objeto $ scope.

$scope.Edit = function (modalParam) {
var modalInstance = $modal.open({
      templateUrl: '/app/views/admin/addeditphone.html',
      controller: function($scope) {
        $scope.modalParam = modalParam;
      }
    });
}

1

Si no está utilizando AngularJS UI Bootstrap, así es como lo hice.

Creé una directiva que contendrá todo ese elemento de su modal y volverá a compilar el elemento para inyectar su alcance en él.

angular.module('yourApp', []).
directive('myModal',
       ['$rootScope','$log','$compile',
function($rootScope,  $log,  $compile) {
    var _scope = null;
    var _element = null;
    var _onModalShow = function(event) {
        _element.after($compile(event.target)(_scope));
    };

    return {
        link: function(scope, element, attributes) {
            _scope = scope;
            _element = element;
            $(element).on('show.bs.modal',_onModalShow);
        }
    };
}]);

Supongo que su plantilla modal está dentro del alcance de su controlador, luego agregue la directiva my-modal a su plantilla. Si guardó el usuario en el que se hizo clic en $ scope.aModel , la plantilla original ahora funcionará.

Nota: El alcance completo ahora es visible para su modal, por lo que también puede acceder a $ scope.users en él.

<div my-modal id="encouragementModal" class="modal hide fade">
  <div class="modal-header">
    <button type="button" class="close" data-dismiss="modal"
      aria-hidden="true">&times;</button>
    <h3>Confirm encouragement?</h3>
  </div>
  <div class="modal-body">
      Do you really want to encourage <b>{{aModel.userName}}</b>?
  </div>
  <div class="modal-footer">
    <button class="btn btn-info"
      ng-click="encourage('${createLink(uri: '/encourage/')}',{{aModel.userName}})">
      Confirm
    </button>
    <button class="btn" data-dismiss="modal" aria-hidden="true">Never Mind</button>
  </div>
</div>
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.