Доступ к свойству Model в файле javascript?
Можно ли получить доступ к свойству Model во внешнем файле Javascript?
например. В файле "somescript.js"
var currency = '@Model.Currency';
alert(currency);
В моем представлении
<script src="../../Scripts/somescript.js" type="text/javascript">
Это не работает, однако, если я поместил javascript непосредственно в представление внутри тегов script, тогда он работает? Это означает, что нужно постоянно помещать код в страницу, а не загружать внешний файл script следующим образом:
@model MyModel;
<script lang=, type=>
var currency = '@Model.Currency';
alert(currency);
</script>
Есть ли способ обойти это?
Ответы
Ответ 1
В JS файлах нет возможности реализовать код MVC/Razor.
Вы должны установить переменные данные в своем HTML (в файлах .cshtml), и это концептуально хорошо и не нарушает разделение проблем (код, созданный сервером HTML и клиентский script), потому что, если вы думаете об этом, эти значения переменных относятся к серверу.
Взгляните на это (частичное, но приятное) обходное решение: Использование Inline С# внутри файла Javascript в MVC Framework
Ответ 2
Я решил эту проблему, используя атрибуты данных, вместе с jQuery. Он обеспечивает очень читаемый код и без необходимости частичного просмотра или запуска статического javascript через ViewEngine. Файл JavaScript полностью статичен и будет обычно кэшироваться.
Index.cshtml:
@model Namespace.ViewModels.HomeIndexViewModel
<h2>
Index
</h2>
@section scripts
{
<script id="Index.js" src="~/Path/To/Index.js"
data-action-url="@Url.Action("GridData")"
data-relative-url="@Url.Content("~/Content/Images/background.png")"
data-sort-by="@Model.SortBy
data-sort-order="@Model.SortOrder
data-page="@ViewData["Page"]"
data-rows="@ViewData["Rows"]"></script>
}
index.js:
jQuery(document).ready(function ($) {
// import all the variables from the model
var $vars = $('#Index\\.js').data();
alert($vars.page);
alert($vars.actionUrl); // Note: hyphenated names become camelCased
});
_Layout.cshtml(необязательно, но хорошая привычка):
<body>
<!-- html content here. scripts go to bottom of body -->
@Scripts.Render("~/bundles/js")
@RenderSection("scripts", required: false)
</body>
Ответ 3
Что вы можете сделать, это передать теги бритвы как переменную.
В бритве Файл >
var currency = '@Model.Currency';
doAlert(currency);
в файле JS >
function doAlert(curr){
alert(curr);
}
Ответ 4
Попробуйте JavaScriptModel (http://jsm.codeplex.com):
Просто добавьте следующий код в действие вашего контроллера:
this.AddJavaScriptVariable("Currency", Currency);
Теперь вы можете получить доступ к переменной "Валюта" в JavaScript.
Если эта переменная должна быть доступна на месте отверстия, поместите ее в фильтр. Пример использования JavaScriptModel из фильтра можно найти в документации.
Ответ 5
Я создал объект js с использованием шаблона вызова метода, после чего вы можете вызвать его из внешнего файла js. Поскольку js использует глобальные переменные, я инкапсулирую их, чтобы не было конфликтов с другими библиотеками js. Пример: в представлении
@section scripts{
<script>
var thisPage = {
variableOne: '@Model.One',
someAjaxUrl: function () { return '@Url.Action("ActionName", "ControllerName")'; }
};
</script>
@Scripts.Render("~/Scripts/PathToExternalScriptFile.js")
}
Теперь внутри внешней страницы вы можете получить данные в защищенной области, чтобы они не конфликтовали с другими глобальными переменными в js.
console.log('VariableOne = ' + thisPage.variableOne);
console.log('Some URL = ' + thisPage.someAjaxUrl());
Также вы можете обернуть его внутри модуля во внешнем файле, чтобы сделать его более защищенным от столкновений. Пример:
$(function () {
MyHelperModule.init(thisPage || {});
});
var MyHelperModule = (function () {
var _helperName = 'MyHelperModule';
// default values
var _settings = { debug: false, timeout:10000, intervalRate:60000};
//initialize the module
var _init = function (settings) {
// combine/replace with (thisPage/settings) passed in
_settings = $.extend(_settings, settings);
// will only display if thisPage has a debug var set to true
_write('*** DEBUGGER ENABLED ***');
// do some setup stuff
// Example to set up interval
setInterval(
function () { _someCheck(); }
, _settings.intervalRate
);
return this; // allow for chaining of calls to helper
};
// sends info to console for module
var _write = function (text, always) {
if (always !== undefined && always === true || _settings.debug === true) {
console.log(moment(new Date()).format() + ' ~ ' + _helperName + ': ' + text);
}
};
// makes the request
var _someCheck = function () {
// if needed values are in settings
if (typeof _settings.someAjaxUrl === 'function'
&& _settings.variableOne !== undefined) {
$.ajax({
dataType: 'json'
, url: _settings.someAjaxUrl()
, data: {
varOne: _settings.variableOne
}
, timeout: _settings.timeout
}).done(function (data) {
// do stuff
_write('Done');
}).fail(function (jqxhr, textStatus, error) {
_write('Fail: [' + jqxhr.status + ']', true);
}).always(function () {
_write('Always');
});
} else {// if any of the page settings don't exist
_write('The module settings do not hold all required variables....', true);
}
};
// Public calls
return {
init: _init
};
})();
Ответ 6
Вы всегда можете попробовать RazorJs. Это в значительной степени решает не использовать модель в ваших js файлах RazorJs
Ответ 7
У меня была такая же проблема, и я сделал это:
Посмотреть.
'var model = @Html.Raw(Json.Encode(Model.myModel));
myFunction(model);'
Внешний JS.
'function myFunction(model){
//do stuff
}'