AmirG AmirG - 2 months ago 15
AngularJS Question

Why select tag is not updating when opening a modal?

I have a modal as directive. The problem is that when I'm triying to open the modal with data already filled the select tags won't update till the second time that I open modal.

I'm using angular and materializecss . Please note that all the other fields work but the selects doesn't until second time i open modal but in the log always shows the data of scope updated so the problem is that select is not rendering on time or something like that.

JS that opens the modal with filled data

$scope.update = function (customer) {
console.log("selected type id: "+$scope.selectedIdType)

$scope.isUpdating = true;
updateView()
$scope.newCustomer = customer;
var resultSplitTin = customer.tin.split('-');
$scope.inputId = resultSplitTin[1] + (resultSplitTin.length > 2 ? '-' + resultSplitTin[2] : '');
$scope.selectedIdType = resultSplitTin[0];
console.log($scope.inputId)
$scope.inputPhone = customer.phones[0];
$scope.newCustomer.zone = customer.zone;
console.log("selected type id after: "+$scope.selectedIdType)

for (var i = 0; i < $scope.zones.length; i++) {
// console.log(customer.zone + " == " + $scope.zones[i].code);
if (customer.zone == $scope.zones[i].code) {
$scope.newCustomer.zone = $scope.zones[i];
}
}


$('#modalCustomer').openModal();
$('#selectedTaxInput').material_select();
$('#selectedZoneInput').material_select();
$('#selectedIdInput').material_select();


};


Modal HTML (all inputs update but no the selects)

<form class="col s12" >
<div class="row">
<div class="input-field col s4">
<select id="selectedIdInput" ng-options="id for id in idTypes" ng-model="selectedIdType">
<option value="" disabled selected>Elije una opci&oacute;n</option>
</select>
<label>Tipo</label>
</div>
<div class="input-field col s8">
<input id="identification" type="text" class="validate" ng-class="{'valid': inputId.length > 0}"
ng-model="inputId">
<label for="identification"
ng-class="{'active': inputId.length > 0}">Identificaci&oacute;n</label>
</div>
</div>
<div class="input-field col s12">
<input id="name" type="text" class="validate" ng-class="{'valid': newCustomer.name.length > 0}"
ng-model="newCustomer.name">
<label for="name" ng-class="{'active': newCustomer.name.length > 0}">Nombre</label>
</div>
<div class="input-field col s12">
<input id="telephone" type="text" class="validate" ng-class="{'valid': inputPhone.length > 0}"
ng-model="inputPhone">
<label for="telephone" ng-class="{'active': inputPhone.length > 0}">Tel&eacute;fono</label>
</div>
<div class="input-field col s12" >
<textarea id="address" class="materialize-textarea"
ng-class="{'valid': newCustomer.address.length > 0}"
ng-model="newCustomer.address"></textarea>
<label for="address" ng-class="{'active': newCustomer.address.length > 0}">Direcci&oacute;n</label>
</div>

<label style="margin-left:10px">Localidad</label>

<div id="selectedZone" class="input-field col s12 l12" input-field>
<select id="selectedZoneInput" ng-model="newCustomer.zone"
ng-options="item.code as item.name for item in zones track by item.code"
ng-change="showSelected()" watch>
<option value="" disabled selected>Elije una opci&oacute;n</option>
</select>
</div>
</form>


FIX

$scope.update = function (customer) {
console.log("selected type id: "+$scope.selectedIdType)

$scope.isUpdating = true;
updateView()
$scope.newCustomer = customer;
var resultSplitTin = customer.tin.split('-');
$scope.inputId = resultSplitTin[1] + (resultSplitTin.length > 2 ? '-' + resultSplitTin[2] : '');
$scope.selectedIdType = resultSplitTin[0];
console.log($scope.inputId)
$scope.inputPhone = customer.phones[0];
$scope.newCustomer.zone = customer.zone;
console.log("selected type id after: "+$scope.selectedIdType)

for (var i = 0; i < $scope.zones.length; i++) {
// console.log(customer.zone + " == " + $scope.zones[i].code);
if (customer.zone == $scope.zones[i].code) {
$scope.newCustomer.zone = $scope.zones[i];
}
}


$('#modalCustomer').openModal({
ready: function(){
$timeout(function() {
$('#selectedTaxInput').material_select();
$('#selectedZoneInput').material_select();
$('#selectedIdInput').material_select();
});
}
});

};

Answer

This is because you are using jQuery to open the modal and binding the values so the Angular is unaware of the changes. There is a concept of digest cycle due to which Angular updates the view when model value changes and vice-versa.

But here, you are using jQuery to modify data in Angular context so you need to manually tell Angular that something has changed. You can use this by calling $scope.$apply() but it has some limitation i.e. it may fail and throw an exception if the digest cycle is already in progress.

So you can make use of $timeout service.

$('#modalCustomer').openModal();

// Assuming this selector is the modal's selector
$('#modalCustomer').on('shown.bs.modal', function (e) {
    $timeout(function() {
        $('#selectedTaxInput').material_select();
        $('#selectedZoneInput').material_select();
        $('#selectedIdInput').material_select();
    });
});
Comments