angular – debugging an app

noviembre 24, 2017

Peek 2017-11-24 15-39.gif

There’s an excellent article on ionic blog which talks about how to debug an app. It become really handy now that JS Batarang extension stopped working on my google chrome 😥 (Ubuntu 16.04.3 LTS; Chrome Version 62.0.3202.62 (Official Build) (64-bit)).

Peek 2017-11-24 15-23

You just have to identify an element on your page which is associated with an scope and you would see all the variables on that scope through the use of a simple console.log call.

angular.element(targetNode).scope()

sources:
http://blog.ionicframework.com/angularjs-console/

Anuncios

I have an enum in one of our entities like so

private enum ConduccionAlProceso {
        POR_COMPARECENCIA, POR_CITACION, CON_CONTROL_DE_DETENCION, EN_CUMPLIMIENTO_DE_ORDEN_DE_APREHENSION
    }

I wanted to display the values on client side without underscores. There are a lot of articles showing how to do so by using a filter directive like

App.filter('underscoreless', function () {
  return function (input) {
      return input.replace(/_/g, ' ');
  };
});

and then in html

{{ addText | underscoreless }}

but I didn’t want to create a directive for this since i’m only using it once.

So, I ended up adding a function in the controller

$scope.mediosConduccionAlProceso = [
    'POR_COMPARECENCIA', 'POR_CITACION', 'CON_CONTROL_DE_DETENCION', 'EN_CUMPLIMIENTO_DE_ORDEN_DE_APREHENSION'
]
$scope.replaceUnderscores = function(item){
    return item.replace(new RegExp('_','g'), ' ');
}

and calling it in the html like

    <select class="form-control"
            ng-model="carpeta.conduccionAlProceso"
            ng-options="medio as replaceUnderscores(medio) for medio in mediosConduccionAlProceso 
                        | orderBy: 'toString()'"
            required>
        <option value=""></option>
    </select>

sources:
https://stackoverflow.com/questions/31939288/angular-filter-to-replace-all-underscores-to-spaces
https://stackoverflow.com/questions/1144783/how-to-replace-all-occurrences-of-a-string-in-javascript
https://stackoverflow.com/questions/21785021/can-ngoptions-call-a-function-to-get-display-text
https://docs.angularjs.org/api/ng/directive/ngOptions

Peek 2017-11-23 08-51

Fuel UX extends Bootstrap with additional lightweight JavaScript controls for your web applications. It has a placard control, which adds a pop-up element to edit inputs/textareas inline on focus with additional options for explicit accept/cancel actions.

I was trying to display a select list -in angular- when the placard is shown. I achieved it with the following code. I had to put the select list inside the placard-popup div and give it a margin so it didn’t overlap with the header. I don’t know if that’s what has been addressed since version 3.11.4 and that’s the purpose of the placard-popup div, it doesn’t say in the docs or at least i couldn’t found it.

<div id="tipoAudiencia" class="placard">
    <div class="placard-popup">
        <div class="form-group" style="margin-top:30px;">



        </div>
    </div>
    <div class="placard-header">Selecciona el tipo de audiencia</div>
    <div class="form-control placard-field glass">{{audiencia.tipoAudiencia.nombre}}</div>
    <div class="placard-footer">
        <a class="placard-cancel" href="#">Cancelar</a>
        Aceptar
    </div>
</div>

then in my controller I update the value if it gets accepted

$('#tipoAudiencia').on('accepted.fu.placard', function(){
    console.log('actualizando el tipo de audiencia a ' + $scope.tipoAudienciaEditada);
    $scope.audiencia.tipoAudiencia = $scope.tipoAudienciaEditada;
    Audiencia.update($scope.audiencia);
});

I had some minor issues with sizing but they’re not showstoppers

Peek 2017-11-23 08-52

sources:
https://github.com/ExactTarget/fuelux/issues/1392

I’ve had a lot of troubles to display a datetimepicker inside a bootstrap modal window. I’ve tried several ways to display the datetimepicker but none of them worked (delegate, z-index, etc.)

The problem I think, is we tried to initialize the datetimepicker before it gets added to the DOM, because of the animation on the modal window.
I tried also to initialize the datetimepicker on the ‘opened’ event of the modal window like so

<div class="row">
            <div class="'col-sm-3'">
                <div class="form-group">
                    <div class="'input-group" id="'datetimepicker'">

                        <span class="input-group-addon">
                            <span class="glyphicon glyphicon-time"></span>
                        </span>
                    </div>
                </div>
            </div>
        </div>
var modal = $modal.open({
      templateUrl: ...,
      controller: ...
});
modal.result.then(function (result) {
     $state.go('avisos', null, {reload: true});
}, function () {
    $state.go('^');
 });

modal.opened.then(function(){
     console.log('modal opened');
     $('#datetimepicker').datetimepicker({ format: 'DD/MM/YYYY'});
});

the event gets fired before the datetimepicker is in place and therefore not initialized correctly. So, the solution for me was to initialize the datetimepicker in a timeout function inside my angular controller

setTimeout(function () {
     $('#datetimepicker').datetimepicker({
         format: 'DD/MM/YYYY'
     });
}, 1000);

ng-if, ng-hide y ng-show nos sirven para mostrar u ocultar algún elemento de nuestra interfaz, pero lo hacen de forma diferente.

ng-if remueve el elemento del DOM, mientras que ng-hide o ng-show sólo lo ocultan mediante atributos HTML. En AngularJS esta diferencia es importante ya que además de esto, el primero crea un nuevo scope y los otros no. Esto quiere decir que para utilizar las variables de nuestro scope principal tenemos que hacerlo a través del atributo $parent o utilizando un objeto para almacenar nuestras variables, ya que al hacerlo así el mecanismo de js buscaría la propiedad en el scope actual y si no la encuentra la buscaría en el padre.

usando $parent

<input type="text" ng-model="data">
<div ng-if="true">
    <input type="text" ng-model="$parent.data">
</div>

utilizando un objeto

<input type="text" ng-model="data.input">
<div ng-if="true">
    <input type="text" ng-model="data.input">
</div>

Fuentes:
http://stackoverflow.com/questions/19177732/what-is-the-difference-between-ng-if-and-ng-show-ng-hide

En Java y C# es muy común utilizar la sobrecarga de operadores para, por ejemplo, tener un método con el mismo nombre pero distintos parámetros.

    public String sayHi(String name){
        return "hi " + name +"!";
    }

    public String sayHi(String first, String last){
        return sayHi(first + " " + last);
    }

    public String sayHi(String first, String last, String city){
        return sayHi(first, last) + "from " + city;
    }

En javascript no existe la sobrecarga de operadores. Pero podemos hacer algo parecido si pasamos un objeto como parámetro a nuestra función, por ejemplo

$scope.sayHi = function(options){
    var greeting = 'hi '
    if(typeof options.first !== 'undefined' && typeof options.last !== 'undefined' && typeof options.city !== 'undefined'){
        greeting += options.first + ' ' + options.last + ' from ' + options.city
    }else if(typeof options.first !== 'undefined' && typeof options.last !== 'undefined'){
        greeting += options.first + ' ' + options.last
    }
    else if(typeof options.name !== 'undefined'){
        greeting += options.name
    }
    return greeting + '!'
}

Fuentes:
http://stackoverflow.com/questions/456177/function-overloading-in-javascript-best-practices
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters

Fuentes:

http://stackoverflow.com/questions/23455718/why-is-my-ng-model-variable-undefined-in-controller
http://jimhoskins.com/2012/12/14/nested-scopes-in-angularjs.html