Como passar parâmetros para um modal?

96

Eu quero passar o userNamede uma lista de userNamecliques de usuários sa logados para o bootstrap do Twitter modal. Estou usando grails com angularjs , onde os dados são renderizados por angularjs .

Configuração

Minha página de visualização grails encouragement.gspé

<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>

Meu encourage/_encouragement_modal.gspé

<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>

Então, como posso passar userNamepara encouragementModal?

prayagupd
fonte
1
Você deve lidar com essas coisas usando angularjs. checkout ng-include.
zs2020

Respostas:

149

Para passar o parâmetro você precisa usar resolver e injetar os itens no controlador

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

Agora, se você usará assim:

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

neste caso, editId será indefinido. Você precisa injetá-lo, assim:

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

Agora vai funcionar bem, eu enfrento o mesmo problema muitas vezes, uma vez injetado, tudo começa a funcionar!

Ali Adravi
fonte
Como qualquer coisa Angular, a injeção é a solução. Obrigado!
Sebastialonso
esse erro indefinido estava fazendo minha cabeça até que eu vi sua resposta! Funciona como um encanto!
Dan
Como você faria se, em vez de simplesmente var, quiser passar algum objeto de tempo limite? a resolução não disparará até que o tempo limite seja resolvido, o que acontece no final do tempo limite
Danny22
O que estava faltando na minha solução era usar $ scope e $ location entre aspas simples ... Eu não sabia que esses argumentos tinham que ser strings
rshimoda
1
Ao fazer isso, obtenho "angular.js: 10071 Erro: [$ injector: despr] Provedor desconhecido: editIdProvider <- editId". Alguma ideia?
Oskar Lund
57

O outro não funciona. De acordo com os documentos, é assim que se deve fazer.

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;
};

Veja plunkr

bicicleta
fonte
1
Você não deve envolver isso como ['$ scope', '$ modalInstance', function () para injetar dependências?
joseramonc
1
Obrigado pelo comentário, José, esse foi exatamente o meu problema. Se você está minimizando seu código Angular, sim, você deve usar a sintaxe de array para o ModalInstanceCtrl.
mcole
José, +1 O problema também foi meu. E eu penso em todos que usam AngularUI!
Matteo Defanti
50

Alternativamente, você pode criar um novo escopo e passar por parâmetros através da opção de escopo

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

Em sua passagem de controlador modal em $ scope, você não precisa passar e itemsProvider ou o que quer que seja que você nomeou

modalController = function($scope) {
    console.log($scope.params)
}
Mwayi
fonte
2
$ rootScope. $ new (); <=== isto deve ser votado positivamente. truque muito legal. obrigado!
reflog 02 de
3
+1 Uma vez que isso permite a passagem de dados sem ter que definir um controlador para o modal. BTW, você pode simplesmente fazer $scope.$new(true)para criar um novo escopo isolado sem a necessidade de injetar $rootScope.
Santosh
@Mwayi: Obrigado por essa dica! O problema com a injeção clássica (usando resolve) é que os argumentos são obrigatórios, então toda vez que você abre um modal, você deve resolver todos os argumentos ou a chamada para $modal.open()falhará porque o controlador deseja seus argumentos. Usando esse scopetruque bacana , as dependências se tornam opcionais.
stackular de
23

Você também pode passar parâmetros facilmente para o controlador modal adicionando uma nova propriedade com a instância de modal e obtê-la para o controlador modal. Por exemplo:

A seguir está o meu evento de clique no qual desejo abrir a visualização 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...
                }]);
Rubi Saini
fonte
Exatamente o que eu precisava. Funcionou perfeitamente.
theFish
17

Eu tentei como abaixo.

Liguei ng-clickpara o controlador do angularjs no botão Encourage ,

               <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>

Eu conjunto userNamede encouragementModaldo controlador angularjs.

    /**
     * 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' ];

Eu forneci um place ( userName) para obter o valor do controlador angularjs ativado 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>

Funcionou e eu me saudei.

prayagupd
fonte
3
Eu +1 e saúdo você. Se alguém precisar passar o usuário inteiro para o modal em vez de uma única string para seu nome, no controlador, lembre-se de usar angular.copy(user).
youri
10

Você realmente deve usar a interface do usuário Angular para essas necessidades. Confira: Diálogo de IU Angular

Em poucas palavras, com a caixa de diálogo Angular UI, você pode passar a variável de um controlador para o controlador de caixa de diálogo usando resolve. Aqui está seu 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();

E em seu controlador de diálogo:

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

EDITAR: desde a nova versão do ui-dialog, a entrada de resolução se torna:

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

Sandro Munda
fonte
Olá, não tentei desta forma. Mas 1 para uma sugestão.
prayagupd
3
na verdade, deveria serresolve: function(){return {username: 'foo'}}
SET
A resposta do SET não funcionará. bicicleta tem isso logo abaixo, deve ser resolvido: {data: function () {return 'foo';}}
bornytm
1
@bornytm Hoje em dia você está certo. Mas quando minha resposta foi escrita, a sintaxe era:resolve: { username: 'foo'}
Sandro Munda
4

Você pode simplesmente criar uma função de controlador e passar seus parâmetros com o objeto $ scope.

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

Se você não está usando o AngularJS UI Bootstrap, veja como fiz isso.

Eu criei uma diretiva que manterá todo esse elemento do modal e recompilará o elemento para injetar seu escopo nele.

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);
        }
    };
}]);

Estou assumindo que seu modelo modal está dentro do escopo do seu controlador, então adicione a diretiva my-modal ao seu modelo. Se você salvou o usuário clicado em $ scope.aModel , o modelo original agora funcionará.

Observação: o escopo inteiro agora está visível para seu modal, portanto, você também pode acessar $ scope.users nele.

<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>
elitechance
fonte