Last Updated: February 25, 2016
·
1.126K
· sbrocos

Rails+Angular+Slim templates

Tenemos una aplicación hecha en Rails(4 en este caso pero creo que funciona igualmente en 3.12) que para el front tira de Angular JS. Este último necesita generar las vistas y para ello usa "templates" que por defecto usan .HTML, pero dado que somos como somos queremos aprovechar la potencia de la gem SLIM para que se ocupe del trabajo enfarragoso que para algo está no?

carpetas (la distribución es opcional):

/app/assets/javascript/angular : carpeta que aglutina la aplicación de angular.js

/app/assets/javascript/angular/controllers : donde iran los controladores

/app/assets/javascript/angular/services : donde van los servicios

/app/assets/javascript/angular/templates : donde van los templates que en nuestro caso serán archivos .html.slim

Para que se puedan procesar los .html.slim en los assets deberemos decirle al Rails que lo haga. Para ello deberemos crear un initializer. Por tanto crearemos el archivo config/initializers/slimengine.rb_
con el contenido:

Rails.application.assets.register_engine('.slim', Slim::Template)

Con esto todo archivo que localice en la carpetas, y subcarpetas, de assets será procesado y compilado como html, por loq ue podremos acceder a él desde el navegador. No se olviden de reiniciar el servidor para que funcione esta nueva configuración.

Luego… en el archivo principal de Angular.js (en mi caso se llama app.js.coffee, porque uso el coffescript) tendremos por ejemplo el siguiente código:

angular.module('myApp', ['ngRoute', 'myApp.controllers'])
.config( ($routeProvider,$locationProvider) ->
    $locationProvider.html5Mode(true)
    $routeProvider.when('/', {
        templateUrl: '/assets/angular/templates/dashboard.html.slim',
        #templateUrl: '/assets/angular/templates/dashboard.html',
        controller: 'HomeController'
}).otherwise({redirectTo: '/'}) 

Como se puede apreciar hay dos líneas de código que incluyen la palabra "templateURL", la primera contiente una url a '/assets/angular/templates/dashboard.html.slim' que hace referencia al archivo .html.slim y la otra (que está comentada), aún archivo .html normal. Para que vean la diferencia.

Con esto ya está. No? Pues… según me he encontrado en varios tutoriales al respeto si. Pero luego… me he encontrado con otra problemática, que quizás vengan porque aún no controlo en exceso el Angular.js. Que se yo.

Como vista (en slim) había traducido el html a lo siguiente:

div ng-repeat="article in articles | orderBy:publishedDate:false"
    .col-lg-10
        div {{article.title}}

Con esta sintaxis debería de mostrarme una lista de articules en orden de más recientes a menos… y en cada punto mostrarme el nombre del article. Pues no. El resultado era

Slim::Parser::SyntaxError como error de cabecera y una descripción

Eso si, mirandolo por consola de javascript del navegador, porque en pantalla simple y llanamente el vacio.

El caso… es que lo de {{article.title}} al slim, por alguna razón que se me escapa le provoca urticaria cuando se trata de un elemento que viene de un bucle. Si usáramos {{articles.length}}, imprimiría el número de elementos de articles sin protestar.

Solución:

div ng-repeat="article in articles | orderBy:publishedDate:false"
    .col-lg-10
        div ng-bind='article.title' 

La clave es div ng-bind='article.title'. Usando esta sintaxis no me ha dado ningún problema para mi alivio (ya que he perdido no sé cuanto tiempo buscando la solución a mis problemas).