Angularjs: Change scope in ngRepeat

Asked

Viewed 440 times

0

I have the situation: in the table below, when I click on "edit", displays the form with the required fields (including with a new "cancel" button). So far everything is working well. The problem is that when saving, the form should disappear (ng-Hide) and present the normal data again. Just below there is an excerpt with JS. As far as I understand I’m not managing to change the "Editing" after saving.

Table with phones

<form name="telefoneEdit">
    <table class="table table-hover">
        <thead>
            <tr>
                <th width="30%">Telefone</th>
                <th width="20%">Ramal</th>
                <th width="40%">Descrição</th>
                <th width="10%"></th>
            </tr>
        </thead>
        <tbody ng-repeat="telefone in clienteCtrl.cliente.ClienteTelefone" ng-form="tel" ng-init="editing = false">
            <tr ng-show="!editing">
                <td>{{telefone.tel}}</td>
                <td>{{telefone.ramal}}</td>
                <td>{{telefone.descricao}}</td>
                <td class="text-center">
                    <a ng-click="editing = true" class="btn btn-default btn-xs"><i class="icon-pencil2"></i></a>
                </td>
            </tr>
            <tr ng-show="editing">
                <td>
                    <div class="col-md-4">
                        <input ng-model="telefone.ddd" type="number" name="ddd" max="99" ng-maxlength="2" class="form-control input-sm"></input>
                        <label class="error" ng-show="tel.ddd.$invalid">Campo inválido</label>
                        <label class="error" ng-show="erros.ddd">{{erros.ddd[0]}}</label>   
                    </div>
                    <div class="col-md-8">
                        <input type="number" name="telefone" ng-model="telefone.telefone" class="form-control input-sm" ng-minlength="8" required></input>
                        <label class="error" ng-show="tel.telefone.$invalid">Campo inválido</label> 
                    </div>                                  
                </td>
                <td>
                    <input ng-model="telefone.ramal" class="form-control input-sm"></input>
                </td>
                <td>
                    <input ng-model="telefone.descricao" class="form-control input-sm"></input>
                </td>
                <td class="text-center">
                    <button class="btn btn-default btn-xs" type="button" ng-click="editTelefone(telefone)"><i class="icon-disk"></i></button>
                    <a ng-click="editing = false" class="btn btn-default btn-xs"><i class="icon-close"></i></a>
                </td>
                <input type="hidden" ng-model="telefone.id" />
            </tr>
        </tbody>
    </table>
</form> 

Excerpt from the JS that should work

$scope.editTelefone = function(telefone) {            
    var erros = {};
    var _data = {};
    _data.ClienteTelefone = telefone;
    self.editing = false;
    $http
        .post('api/cliente_telefones/edit.json',_data)
        .success(function(data){
            if(data.erros) {
                $scope.erros = data.erros;
            } 
            else {
                self.telefone = telefone;
                $scope.erros = false;
                $scope.editing = false;
            }
        })
}

Everything works correctly, I just can’t hide the form again.

Illustrative images

Tabela em seu estado original/inicial Table in its original/initial state

Form de edição Editing form

Resultado após submeter o form de edição Result after submitting the editing form

  • You put the tag angularjs-directives, this JS code you posted is inside a Directive? or a controller?

  • Is in a controller

  • You were able to verify if you’re getting any feedback inside the success? If the result you expect is really coming?

  • @Celsomtrindade is all working correctly: the data is sent and saved in the database without problems. But $Scope.Editing = false is not reflecting any effect. This is the problem.

1 answer

1


One point to be noted is the use of self. I could be wrong, but as far as I know, in the controller we use this or, more commonly used through syntax vm thus:

var vm = this;

But it would be necessary to change the syntax of the controller in the GIFT to controller as vm and all the values of scope should have the prefix vm. ex.: ng-show="vm.editing". Since this is not your case, I recommend that you do not use the self and use directly $scope.

Another observation to be made is on the definition of ng-repeat. You stated directly on the tag tbody, which is not advisable. As you need to repeat 2 blocks of tr you must use an option from ng-repeat that, even, is very little used/commented, that would be:

ng-repeat-start="item in items"
&
ng-repeat-end

In your case, it should be used like this:

<tr ng-show="!editing" ng-repeat-start="telefone in clienteCtrl.cliente.ClienteTelefone">
    //.. restante do primeiro bloco de código
</tr>
<tr ng-show="editing" ng-repeat-end>
    //.. restante do bloco de edição
</tr>

As for the problem itself of hiding the form after editing, the problem happens because the variable $scope.editing is set within ng-repeat, i.e., for each block that repeats, there will always be this variable, so it will enable/disable all at once.

One solution I used when I had a similar problem was to create a new field within the array and control the display from that field, leaving its array like this for example:

$scope.telefones = [
    {id:1, visible: false, telefone: '(48)99665588'},
    //..mais objetos
]

And within the controller, we would control the display according to the "Visible" field, so only the desired object will be able to edit.

$scope.mostraEdit = function(id) {
  $filter('filter')($scope.telefones, {id: id})[0].visible = true;
};
$scope.escondeEdit = function(id) {
  $filter('filter')($scope.telefones, {id: id})[0].visible = false;
};
$scope.salvaTelefone = function(data) {
  $filter('filter')($scope.telefones, {id: data.id})[0].visible = false;
};

And in the DOM we would have that:

<tr ng-show="!telefone.visible" ng-repeat-start="telefone in telefones" ng-form="tel">
  //.. listagem de telefones
</tr>
<tr ng-show="telefone.visible" ng-repeat-end>
    //.. formulario de edição
</tr>
  • Excellent observations. I will test and report the result. As for self, it is previously set in the code as a var self = this

  • Right. So it’s okay to use the definition of self but remember, it won’t work unless you change all the syntax of your code. In this case, recommend not using as self because you are using the reference of $scope in DOM and Controller. Or change everything to syntax as I mentioned, or switch to $scope.variavel

  • I’ve been applying your suggestions. The ng-repeat question was perfect. But the big problem, which is to hide the form when the answer is correct, ie setting '$Scope.Editing = false' still does not work. I will add in the posting images exemplifying the case.

  • Have you replaced the use of self within the editTelefone() ?

  • Yes, I’ve done it before.

  • Strange.. in the simplified example I created with your code (i.e., without http) it worked all right.. Try to leave the function of editTelefone only with the $scope.editing = false; and see what happens.

  • I commented everything, I just left .success(function(data){ $scope.editing = false; } and yet it doesn’t work...

Show 3 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.