Use View model in Javascript - javascript

Scenario:
A partial view has a model, I need to use the value from the model in the javascript which is in seperate .js file.
Currently, I'm using javascript inline so that the value in the model can be used, but what if, the javascript is moved to a seperate file. In this case how do I get those values.
Code
#model IEnumerable<BookSpec.DomainEntities.ContactModel.ContactDataModel>
<label for="SpecFinder">Contact</label>
<select id="SpecFinder" name="state">
#foreach (var name in Model)
{
<option value="#name.GroupID">#name.GroupName</option>
}
</select>
<script type="text/javascript">
$(document).ready(function () {
$("#SpecFinder").change(function(){
getData(this.value,'#Model.ProductID');
});
})
</script>
This is my current example code looks like, and I want to completely move the inline javascript to a seperate file. How can I do it, I also need the values from the model.

Declare global javascript variable model on view as below. Then you can use it anywhere.
<script type="text/javascript">
var model = #Html.Raw(Json.Encode(Model));
</script>
I will recommend to use above solution. But if you still want to not include any script in partial view then you can render the model inside any hidden div. And access its text and convert it to object using JSON.parse as below. Code like below is not a good practice and like patch work.
HTML
<div id="model" style="display:none;">
#Html.Raw(Json.Encode(Model))
</div>
Script
var model = JSON.parse($("#model").text());

I think #Karan response is a good option. But if you want no inline Javascript, you could assign your model to a hidden HTML input and then retrive the value in whatever other external JS file you want.
With something like Html.Hidden, for example:
#Html.Hidden("myModel", new Microsoft.Web.Mvc.MvcSerializer().Serialize(model, SerializationMode.Signed));
You can choose another serialization mode in the SerializationMode enum.
(Code not tried, but should be close)

Related

Dynamically update Javascript variables using Jinja?

I have a web form created that requires template creation by the user. Calling all previous entries that are templates isn't an issue, but passing the information to the form when called seems to be tricky. Basically I want the user to be able to select a template from the dropdown (See the screenshots and stuff below), then based on their selection, update the variables in the script to autofill form data. Right now, it only selects the most recent entry. Is this possible just using python/flask/javascript or am I missing something? Any help would be appreciated! Thanks!
Template Dropdown
<label for="template_select">Select Template</label>
<select class="form-control" name="template_select" id='template_select' onchange='changeTemplate()'>
<option value=''></option>
{% for template_info in template_search %}
<option value='{{template_info.client_name}}'>{{template_info.client_name}}</option>
{% endfor %}
</select>
Javascript to change values
{% for template_info in template_search %}
<script>
function changeTemplate(){
var template = document.getElementById('template_select').value;
document.getElementById('client_name').value='{{template_info.client_name}}';
document.getElementById('client_name').innerHTML='{{template_info.client_name}}';
}
</script>
{% endfor %}
Python Passing in the Query
template_search = newmatter_model.NewClientMatter.query.filter_by(
creator=verifier, is_template='on').all()
Your mistake is to create Javascript code in a loop. You don't need to do this.
What you want to do is think of the data sent to the browser as independent. Make it work first without Flask and Jinja2. Create a static page that works and does what you want.
The following code would work with static data:
function changeTemplate(){
var template = document.getElementById('template_select').value;
document.getElementById('client_name').innerHTML = template;
}
<label for="template_select">Select Template</label>
<select class="form-control" name="template_select" id="template_select" onchange="changeTemplate()">
<option value=""></option>
<option value="Client 1">Client 1</option>
<option value="Client 2">Client 2</option>
<option value="Client 3">Client 3</option>
</select>
<div id="client_name"><i>No client set</i></div>
That's HTML for a select box, a separate <div> element, and Javascript code to copy the selected option value into the <div>. Note that the Javascript code doesn't know anything about what data is involved; no client names are stored in the code. All that the small function does is to copy the value from the currently selected option, to somewhere else.
Once that works on its own you can start thinking about how you are going to insert the values from your application. In the above code, all that needs replacing is the dropdown options, because the Javascript code can then access everything it needs from the <select> element value.
So the Javascript code doesn't need to be generated at all, you only generate the <option> elements, as you already did in your question.
You rarely need to generate dynamic Javascript code, and it would be much better for your app if you don't. Static Javascript code can be served by a CDN and cached in the browser, removing the need for your app to keep serving that again and again for all clients. Try to minimise that whenever you can.
Instead, generate just the data that the code needs to operate on.
You can put that information in HTML tags. In the above example, your data is put in the repeated <option> tags. Or
you could add data attributes to your HTML, which are accessible both to Javascript code and to CSS. Or
use AJAX to load data asynchronously; e.g. when you pick an option in the <select> box, use Javascript and AJAX to call a separate endpoint on your Flask server that serves more data as JSON or ready-made HTML, then have the Javascript code update your webpage based on that. Or
generate JSON data and put it directly into your HTML page. Just a <script>some_variable_name = {{datastructure|tojson|safe}};<script> section is enough; then access that some_variable_name from your static Javascript code to do interesting things on the page. JSON is a (almost entirely a) subset of Javascript, and the way the tojson filter works is guaranteed to produce a Javascript-compatible data structure for you. The browser will load it just like any other embedded Javascript code.

How to pass or use variable from GSP in Javascript

I have below line in my grails gsp file.
<div class="pagination">
<g:paginate total="${lotCount ?: 0}" />
</div>
I want to pass lotCount value to one of my javascript named area-switcher.js file to further use it. How can I do this?
I tried to refer one suggestion from How to pass a value directly from a controller to a javascript file in Grails
where I do below in my gsp
<g:javascript> var theId = ${lotCount} </g:javascript>
and try below in my js file for testing
alert(theId);
but it doesn't work.
Got error like ReferenceError: theId is not defined.
Please help.
Use a hiddenField:
<g:hiddenField name="lotCount" value="${lotCount}" />
<div class="pagination">
<g:paginate total="${lotCount ?: 0}" />
</div>
Your solution should work.
Just ensure that in source of generated html page line
<g:javascript> var theId = ${lotCount} </g:javascript>
is placed before line which includes area-switcher.js
<script type="text/javascript" src="area-switcher.js">
Besides that, there are two more options to pass some value from .gsp to javascript file (examples use jQuery):
By using of data attribute. For example,
gsp (here div, span, input, other tags could be used):
<div id="countElem" data-count="${count}">
js(jQuery used here):
var count = $("#countElem").data('count');
As was mentioned in another comments, by using of hidden field:
gsp:
<g:hiddenField name="countElem" data-count="${count}"/>
js(jQuery used here):
// hidden field will have name and id equals to countElem
var count = $("#countElem").val();

How to load a partialview and store it in a variable to be used in javascript?

I have a prtialview using a model to create a dropdown list.
In my main view I create the partialview html string to use it in javascript functions later.
View:
#model SomeViewModel
#{
var devicesDropDown = #Html.Partial("_DropDown", (SelectList)(Model.DeviceTypes));
var devicesHtmlDropDown = MvcHtmlString.Create(devicesDropDown.ToString());
}
But when I want to use it in javascript this way , it is like a unconnected string that causes javascript function an error.
Js function at the buttom of page:
<script type="text/javascript">
function format(d) {
var ddl = '#( devicesHtmlDropDown)';
return ddl;
}
</script>
This is how string is look like in runtime:
var ddl = '<select class="form-control input" id="SelectedValue" name="SelectedValue" style="width: 100%">
<option selected="selected" value="456413">1</option>
<option value="564655465">2</option>
</select>
';
How should I format this string to can render like a static html object.
And how can I retrive selected value of this dropdown to post to an action?
Should I use TagBuilder?
My suggestion would be to use a script block to hold your template. You can easily retrieve the HTML from there by ID. The script block will never be directly rendered, so it is safely hidden until you extract and apply the HTML.
<script id="ddlTemplate" type="text/html">
#Html.Partial("_DropDown", (SelectList)(Model.DeviceTypes))
</script>
Then later, you can access this HTML like so (using jQuery)
var template = $('#ddlTemplate').html();

Embed same web widget multiple times with different data attribute values

I want to create a web widget that can be embedded multiple times on the same page but with different data attribute values so I can display different data according to the data attribute value.
For example, I want to embed mywidget.js file multiple times as follows:
<body>
<div>
<script src="script/mywidget.js" data-sport="soccer" id="widget-soccer">
</script>
</div>
<div>
<script src="script/mywidget.js" data-sport="tennis" id="widget-tennis">
</script>
</div>
</body>
My question is, inside the code in mywidget.js, how do I determine the correct script tag reference and read it's data attribute so I can use that value to fetch the corresponding data from a web service. I am using only jquery and javascript.
I want the widget to be embeddable on other users sites as well so all they do is embed using only the script tag and passing in the desired data attribute value without adding anything extra anywhere they need on their website.
This is not really a very good approach, as it is very inflexible. But given that <script> tags, when not deferred, halt parsing of the document while they execute, the current script tag will be the last in the DOM; so you can get the current sport inside your script by using this:
var sport = $('script').last().data('sport');
However, it would be much better to define a function in your external JavaScript file, and then invoke it when you need to instantiate your widget (EDIT: like in Lee Taylor's answer).
Why don't you do something like:
<head>
<script src="script/mywidget.js"></script>
</head>
<body>
<div><script>createMyWidget({sport : "soccer"} );</div>
<div><script>createMyWidget({sport : "tennis"} );</div>
</body>
I don't think you can. I know it's not that nice, but I would try:
<div><script>sport = "soccer";</script><script src="script/mywidget.js" id="widget-soccer"></script></div>
<div><script>sport = "tennis";</script><script src="script/mywidget.js" id="widget-tennis"></script></div>
and use sport in mywidget.js
Another approach could be that myscript.js is actually a dynamic "page", let's say with php, then you could use src="script/mywidget.js?sport=swimming", and in the php you would print:
sport = "<?php echo addcslashes($_GET['sport'], '"'); ?>";
But even better would be:
<script src="script/mywidget.js"></script>
<div><script>showWidget("soccer");</script></div>
<div><script>showWidget("basketball");</script></div>
I think you can use jQuery to find all script tags with src="script/mywidget.js" or something
$('script[src="script/mywidget.js"]')
And then you'll have an array of scripts tags that you can loop through and access the data property using jQuery's .data() method.

Interpret variable in Javascript file Laravel

I need to include a js file in my views.
But in this js file i need to interpret somes PHP variable.
Actually i do this :
#section('javascript')
<script>
alert("{{{test}}}");
</script>
#stop
But i REALLY need to do this :
#section('javascript')
{!! Html::script('js/test.js') !!}
#stop
test.js :
alert("{{{test}}}");
I need to declare a lot o variable. So my JS file will be very huge. And i don't want to show this directly in the source code.
How can i do ?
Thank you !
You can only pass the variable to the javascript like so:
#section('javascript')
<script>
var test = {{{$test}}};
</script>
#stop
then in your javascript file included at the bottom you can use it:
alert(test);
Let me just mention that this is not a great way of handling the passing variables from php to javascript.
When I need to do something like this, I usually create a meta tag on the page which would contain the alert information.
<meta name="someAlertValue" content="{{{ $test }}}" />
Then you can very easily grab that via jQuery.
var alert_text = $('meta[name=someAlertValue]').attr('content');
I find this approach to be much cleaner and maintainable than trying to drop php variables directly into your javascript.
I had the same problem, and wanted to have a stand alone js which will have bunch of variables taken from config() or even from database, multi-language, and will be configurable, or even will work with query parameters.
Maybe it's a hard way, but i've created a route:
Route::get('/js-modules/test.js',function(){ return view('js-modules.test');})->name('my_js);
So in the view resources/views/js-modules/test.blade.php you can put your js code together with your PHP stuff.
Or you can route it to a controller and have even more background work. it looks a bit slow (in the browser) on the first run , but second request it'll be cashed and retrieved as the regular js file
And now you can link it to any of your pages with
<script src="{{route('my_js')}}"></script>

Categories

Resources