selecionando o objeto ng com ng-change

313

Dado o seguinte elemento de seleção

<select ng-options="size.code as size.name for size in sizes " 
        ng-model="item.size.code" 
        ng-change="update(MAGIC_THING)">
</select>

Existe uma maneira de fazer com que MAGIC_THING seja igual ao tamanho atualmente selecionado, para que eu tenha acesso ao size.namee size.codeno meu controlador?

size.code afeta muitas das outras partes do aplicativo (URLs de imagem, etc.), mas quando o modelo ng item.size.codeé atualizado, ele item.size.nameprecisa ser atualizado também para as coisas que o usuário enfrenta. Suponho que a maneira correta de fazer isso é capturar o evento de alteração e definir os valores dentro do meu controlador, mas não tenho certeza do que posso atualizar para obter os valores adequados.

Se esse for o caminho totalmente errado, eu adoraria saber o caminho certo.

Patrick
fonte

Respostas:

488

Em vez de definir o ng-model como item.size.code, que tal configurá-lo para o tamanho:

<select ng-options="size as size.name for size in sizes" 
   ng-model="item" ng-change="update()"></select>

Em seguida, no seu update()método, $scope.itemserá definido como o item atualmente selecionado.

E qualquer código necessário item.size.code, pode obter essa propriedade via $scope.item.code.

Violino .

Atualização com base em mais informações nos comentários:

Use alguma outra propriedade $ scope para seu modelo ng selecionado:

<select ng-options="size as size.name for size in sizes" 
   ng-model="selectedItem" ng-change="update()"></select>

Controlador:

$scope.update = function() {
   $scope.item.size.code = $scope.selectedItem.code
   // use $scope.selectedItem.code and $scope.selectedItem.name here
   // for other stuff ...
}
Mark Rajcok
fonte
1
Se eu definir meu modelo como item, como pré-seleciono um valor?
Patrick
5
Coloque isso dentro do seu <select>: ng-init = "item =
size
Muito obrigado por sua ajuda, mas não creio ter compartilhado o suficiente da situação. item é um objeto criado para carregar a página. a matriz de tamanhos de objetos entra na interação do usuário com um botão de edição; portanto, se eu fizer isso, ele substituirá todo o objeto do item. Eu preciso de uma maneira de criar um monte de opções em uma caixa de seleção que pré-seleciona um valor de uma parte completamente separada do objeto de dados.
Patrick
14
Isso é verdade? Parece que o manipulador ng-change é acionado antes da atualização do modelo ng, portanto, tentar $ scope.item.size.code = $ scope.selectedItem.code nem sempre fornece o valor do modelo atualizado. Alguém viu isso ao usar ng-change?
Karl
6
Acho que não há nada impedindo você de fazer isso:ng-model="selectedItem" ng-change="update(selectedItem)"
Rhys van der Waerden
52

Você também pode obter diretamente o valor selecionado usando o seguinte código

 <select ng-options='t.name for t in templates'
                  ng-change='selectedTemplate(t.url)'></select>

script.js

 $scope.selectedTemplate = function(pTemplate) {
    //Your logic
    alert('Template Url is : '+pTemplate);
}
Divyesh Rupawala
fonte
5
Esta resposta à pergunta enquanto o aceite dá uma alternativa
redben
1
onde você inicializa ou obtém a variável de modelo?
Kat Lim Ruiz #
29
Isso funciona sem especificar um modelo? Recebo este erro: Não é possível encontrar o controlador 'ngModel', exigido pela diretiva 'select'!
fer
8
O ngModel é definitivamente necessário para selecionar elementos, de acordo com a documentação. As outras diretivas são opcionais, mas essa não é.
Mnemia #
26
Isso não funciona! ng-change não tem acesso à variável temporária (t) criada dentro das ng-options.
Garbage
16

você também pode tentar o seguinte:

<select  ng-model="selectedItem" ng-change="update()">
<option ng-repeat="item in items" ng-selected="selectedItem == item.Id" value="{{item.Id}}">{{item.Name}}</option>
</select>
DolceVita
fonte
2
Esta solução é boa se você precisar formatar o valor. Usando apenas a abordagem Select, não pude formatar o valor facilmente.
mbokil
7

Se a resposta de Divyesh Rupawala não funcionar (passando o item atual como parâmetro), consulte a onChanged()função neste Plunker. Está usando this:

http://plnkr.co/edit/B5TDQJ

abbaf33f
fonte
2
<select ng-model="item.size.code">
<option ng-repeat="size in sizes" ng-attr-value="size.code">{{size.name}}          </option>
</select>
Jignesh Variya
fonte
11
Use ng-options em vez de ng-repeat em uma seleção.
Jepser Bernardino
12
@JepserBernardino em algum momento você precisa de um acesso mais refinado à <opção>, por exemplo, para estilizar algumas opções especiais / padrão, independentemente de elas estarem selecionadas ou não
Ekus
2

//Javascript
$scope.update = function () {
    $scope.myItem;
    alert('Hello');
}
<!--HTML-->
<div class="form-group">
     <select name="name"
             id="id" 
             ng-model="myItem" 
             ng-options="size as size.name for size in sizes"
             class="form-control" 
             ng-change="update()"
             multiple
             required>
     </select>
</div>

Se você deseja escrever, nome, ID, classe, múltiplos, obrigatório, você pode escrever dessa maneira.

barış çıracı
fonte
1

Isso pode lhe dar algumas idéias

Modelo de exibição C # .NET

public class DepartmentViewModel
{
    public int Id { get; set; }
    public string Name { get; set; }
}

Controlador da API do .NET C # Web

public class DepartmentController : BaseApiController
{
    [HttpGet]
    public HttpResponseMessage Get()
    {
        var sms = Ctx.Departments;

        var vms = new List<DepartmentViewModel>();

        foreach (var sm in sms)
        {
            var vm = new DepartmentViewModel()
            {
                Id = sm.Id,
                Name = sm.DepartmentName
            };
            vms.Add(vm);
        }

        return Request.CreateResponse(HttpStatusCode.OK, vms);
    }

}

Controlador angular:

$http.get('/api/department').then(
    function (response) {
        $scope.departments = response.data;
    },
    function (response) {
        toaster.pop('error', "Error", "An unexpected error occurred.");
    }
);

$http.get('/api/getTravelerInformation', { params: { id: $routeParams.userKey } }).then(
   function (response) {
       $scope.request = response.data;
       $scope.travelerDepartment = underscoreService.findWhere($scope.departments, { Id: $scope.request.TravelerDepartmentId });
   },
    function (response) {
        toaster.pop('error', "Error", "An unexpected error occurred.");
    }
);

Modelo angular:

<div class="form-group">
    <label>Department</label>
    <div class="left-inner-addon">
        <i class="glyphicon glyphicon-hand-up"></i>
        <select ng-model="travelerDepartment"
                ng-options="department.Name for department in departments track by department.Id"
                ng-init="request.TravelerDepartmentId = travelerDepartment.Id"
                ng-change="request.TravelerDepartmentId = travelerDepartment.Id"
                class="form-control">
            <option value=""></option>
        </select>
    </div>
</div>
meffect
fonte
1

Você precisa usar "rastrear por" para que os objetos possam ser comparados corretamente. Caso contrário, o Angular usará a maneira js nativa de comparar objetos.

Portanto, seu código de exemplo mudaria para -

    <select ng-options="size.code as size.name
 for size in sizes track by size.code" 
ng-model="item.size.code"></select>
dworrad
fonte
1

O filtro do AngularJS funcionou para mim.

Supondo que code/idseja único , podemos filtrar esse objeto específico com AngularJS filtere trabalhar com as propriedades dos objetos selecionados. Considerando o exemplo acima:

<select ng-options="size.code as size.name for size in sizes" 
        ng-model="item.size.code" 
        ng-change="update(MAGIC_THING); search.code = item.size.code">
</select>

<!-- OUTSIDE THE SELECT BOX -->

<h1 ng-repeat="size in sizes | filter:search:true"
    ng-init="search.code = item.size.code">
  {{size.name}}
</h1>

Agora, existem três aspectos importantes para isso :

  1. ng-init="search.code = item.size.code"- na inicialização do h1elemento fora da selectcaixa, defina a consulta de filtro para a opção selecionada .

  2. ng-change="update(MAGIC_THING); search.code = item.size.code"- quando você alterar a entrada de seleção, executaremos mais uma linha que definirá a consulta de "pesquisa" para a selecionada no momento item.size.code.

  3. filter:search:true- Passe truepara o filtro para ativar a correspondência estrita .

É isso aí. Se o size.codeé ID exclusivo , teremos apenas um h1elemento com o texto de size.name.

Eu testei isso no meu projeto e funciona.

Boa sorte

Akash
fonte
0

Essa é a maneira mais limpa de obter um valor de uma lista de opções de seleção angular (diferente de Id ou texto). Supondo que você tenha um Product Select como este em sua página:

<select ng-model="data.ProductId"
        ng-options="product.Id as product.Name for product in productsList"
        ng-change="onSelectChange()">
</select>

Em Seu controlador, defina a função de retorno de chamada da seguinte maneira:

    $scope.onSelectChange = function () {
        var filteredData = $scope.productsList.filter(function (response) {
            return response.Id === $scope.data.ProductId;
        })
        console.log(filteredData[0].ProductColor);
    }

Simplesmente explicado: como o evento ng-change não reconhece os itens de opção no select, estamos usando o ngModel para filtrar o item selecionado da lista de opções carregada no controlador.

Além disso, como o evento é disparado antes que o ngModel seja realmente atualizado, você pode obter resultados indesejáveis. Portanto, uma maneira melhor seria adicionar um tempo limite:

        $scope.onSelectChange = function () {
            $timeout(function () {
            var filteredData = $scope.productsList.filter(function (response) {
                return response.Id === $scope.data.ProductId;
            })
            console.log(filteredData[0].ProductColor);
            }, 100);
        };
Sagi
fonte