Usando Razor dentro de JavaScript
¿Es posible o existe una solución alternativa para usar la sintaxis de Razor dentro de JavaScript que está en una vista ( cshtml
)?
Estoy intentando agregar marcadores a un mapa de Google... Por ejemplo, intenté esto, pero recibo un montón de errores de compilación:
<script type="text/javascript">
// Some JavaScript code here to display map, etc.
// Now add markers
@foreach (var item in Model) {
var markerlatLng = new google.maps.LatLng(@(Model.Latitude), @(Model.Longitude));
var title = '@(Model.Title)';
var description = '@(Model.Description)';
var contentString = '<h3>' + title + '</h3>' + '<p>' + description + '</p>'
var infowindow = new google.maps.InfoWindow({
content: contentString
});
var marker = new google.maps.Marker({
position: latLng,
title: title,
map: map,
draggable: false
});
google.maps.event.addListener(marker, 'click', function () {
infowindow.open(map, marker);
});
}
</script>
Utilice el <text>
pseudoelemento, como se describe aquí , para forzar que el compilador Razor vuelva al modo de contenido:
<script type="text/javascript">
// Some JavaScript code here to display map, etc.
// Now add markers
@foreach (var item in Model) {
<text>
var markerlatLng = new google.maps.LatLng(@(Model.Latitude), @(Model.Longitude));
var title = '@(Model.Title)';
var description = '@(Model.Description)';
var contentString = '<h3>' + title + '</h3>' + '<p>' + description + '</p>'
var infowindow = new google.maps.InfoWindow({
content: contentString
});
var marker = new google.maps.Marker({
position: latLng,
title: title,
map: map,
draggable: false
});
google.maps.event.addListener(marker, 'click', function () {
infowindow.open(map, marker);
});
</text>
}
</script>
Actualizar:
Scott Guthrie publicó recientemente sobre @:
la sintaxis en Razor, que es un poco menos complicada que la <text>
etiqueta si solo tiene una o dos líneas de código JavaScript para agregar. Probablemente sería preferible el siguiente enfoque, porque reduce el tamaño del HTML generado. (Incluso podría mover la función addMarker a un archivo JavaScript estático en caché para reducir aún más el tamaño):
<script type="text/javascript">
// Some JavaScript code here to display map, etc.
...
// Declare addMarker function
function addMarker(latitude, longitude, title, description, map)
{
var latLng = new google.maps.LatLng(latitude, longitude);
var contentString = '<h3>' + title + '</h3>' + '<p>' + description + '</p>';
var infowindow = new google.maps.InfoWindow({
content: contentString
});
var marker = new google.maps.Marker({
position: latLng,
title: title,
map: map,
draggable: false
});
google.maps.event.addListener(marker, 'click', function () {
infowindow.open(map, marker);
});
}
// Now add markers
@foreach (var item in Model) {
@:addMarker(@item.Latitude, @item.Longitude, '@item.Title', '@item.Description', map);
}
</script>
Se actualizó el código anterior para que la llamada sea addMarker
más correcta.
Para aclarar, @:
obliga a Razor a volver al modo de texto, aunque addMarker
la llamada se parece mucho al código C#. Luego, Razor retoma la @item.Property
sintaxis para decir que debería generar directamente el contenido de esas propiedades.
Actualización 2
Vale la pena señalar que Ver código realmente no es un buen lugar para colocar código JavaScript. El código JavaScript debe colocarse en un .js
archivo estático y luego debe obtener los datos que necesita, ya sea a partir de una llamada Ajax o escaneando data-
atributos del HTML. Además de permitir almacenar en caché su código JavaScript, esto también evita problemas con la codificación, ya que Razor está diseñado para codificar HTML, pero no JavaScript.
Ver código
@foreach(var item in Model)
{
<div data-marker="@Json.Encode(item)"></div>
}
código javascript
$('[data-marker]').each(function() {
var markerData = $(this).data('marker');
addMarker(markerData.Latitude, markerData.Longitude,
markerData.Description, markerData.Title);
});
Acabo de escribir esta función auxiliar. Ponlo adentro App_Code/JS.cshtml
:
@using System.Web.Script.Serialization
@helper Encode(object obj)
{
@(new HtmlString(new JavaScriptSerializer().Serialize(obj)));
}
Luego, en tu ejemplo, puedes hacer algo como esto:
var title = @JS.Encode(Model.Title);
Observe cómo no lo pongo entre comillas. Si el título ya contiene comillas, no explotará. ¡Parece manejar muy bien diccionarios y objetos anónimos también!
Estás intentando meter una clavija cuadrada en un agujero redondo.
Razor fue pensado como un lenguaje de plantilla generador de HTML. Es muy posible que consigas que genere código JavaScript, pero no fue diseñado para eso.
Por ejemplo: ¿Qué pasa si Model.Title
contiene un apóstrofe? Eso rompería su código JavaScript y Razor no escapará correctamente de forma predeterminada.
Probablemente sería más apropiado utilizar un generador de cadenas en una función auxiliar. Probablemente habrá menos consecuencias no deseadas de ese enfoque.
¿Qué errores específicos estás viendo?
Algo como esto podría funcionar mejor:
<script type="text/javascript">
//now add markers
@foreach (var item in Model) {
<text>
var markerlatLng = new google.maps.LatLng(@Model.Latitude, @Model.Longitude);
var title = '@(Model.Title)';
var description = '@(Model.Description)';
var contentString = '<h3>' + title + '</h3>' + '<p>' + description + '</p>'
</text>
}
</script>
Tenga en cuenta que necesita la <text>
etiqueta mágica después de foreach
para indicar que Razor debe cambiar al modo de marcado.