Best way to store .resx string in an object? - javascript

In my application I added the multilanguage support following this documentation.
Now I'm facing an issue: I need to translate also some javascript plugins, so I need to use the .resx string inside the js logic:
For access to those strings I can use the IStringLocalizer in the specific controller, let's suppose that the string above are part of UserController, I can access declaring in the View this:
#inject IStringLocalizer<UserController> Localizer
and then:
<h2>#Localizer["LastName"]</h2>
Suppose now that I need to pass LastName string in something like a JQuery plugin
localization. For doing so, I actually found a workaround, which consists to declare a javascript variable in the required View:
#inject IStringLocalizer<UserController> Localizer
#section UserScript{
<script>
var Lang = {
PasswordEqual: '#Localizer["PasswordEqual"]',
PasswordMismatch: '#Localizer["PasswordMismatch"]',
}
</script>
}
so I can access inside the javascript code to the Lang object and localize the plugin eg:
$('#birthDate').daterangepicker({
singleDatePicker: true,
locale: {
format: 'DD/MM/YYYY',
daysOfWeek: [
Lang.Sunday,
Lang.Monday,
This works, but it's really huge to mantain for the following reason:
I need to declare in each .cshtml file which require a script localization the Lang object
I need to set each time the object key for the specific string available in the IStringLocalizer
If I change a string key, I also need to update all the files manually.
What I'm looking for:
I'm looking for a solution that automatically fills the Lang object with all the properties available in the .resx file loaded in the current View.
I guess the best place for handle this is _Layout.
Someone could help me?

Related

Passing Object from ASP.Net to javascript

I have an ASP.Net Core application. I have a Class with some attributes:
public class myClass
{
public string name {get; set;}
public int id{get; set;}
...
}
and in PageModel of Index.cshtml, I am creating on object of that class and setting it is a property:
public class IndexModel : PageModel
{
public myObj data { get; set; }
public void OnGet(int inputId)
{
data = new myClass();
data.name = "name";
data.id = inputId;
}
}
Now, in my Index.cshtml, I have some default html and then I add a script like this:
<script type="module" src="~/built/script.js"></script>
Finally, my question: I need the data that I have defined in IndexModel in my script.js. In a normal cshtml-page, I would do #Model.data, but that decorator is not available in my js file. Is there a way to do this, or should I use one of the following which I think might work:
Adding an API-controller in ASP.Net and calling it in my script.js with ajax: I think this should work, but it seems to me like I am supposed to do it with #Model instead
Somehow storing it in a global variable in my .cshtml file and then accessing that global variable in script.js: Seems like a hack
I'm pretty new to ASP.Net and JS, so there might be an obvious answer to this that I'm just too inexperienced to know. Any help is appreciated!
You could use model binding as intended and convert the model to a javascript variable at the top of your view, then it will be available in the script file as a javascript variable as long as you load the javascript file after you create the variable to hold your model.
---YOUR VIEW---
#model YourModel
#using Newtonsoft.Json;
<script type="text/javascript">
let mymodel = #Html.Raw(JsonConvert.SerializeObject(Model));
</script>
--Import your script file after creating javascript variable and mymodel should then be available
<script type="text/javascript" src=""></script>
--Use mymodel in your script file
There are four ways to do this, you found two of them. I'll give you the pro's and cons in order of complexity:
AJAX:
It's not that hard, use the "fetch" method built into the window object. But, it's asynchronous so you have to deal with callbacks in JavaScript, you will need to secure the API so it only accepts authorized clients (usually done with OAuth, but you could just inject an authorization code for the client JavaScript to use), and you need to identify yourself (like a session) to the API to get the right data so that is another code. Oh wait, we have to inject a code? So what's the point of using AJAX? True, only use AJAX when you need to dynamically get new data without reloading the page!
JavaScript injection:
You never want to inject into a .js file, they should be static and that's why you discovered it won't work. So you have to inject some JavaScript code creating variables into the page that is loading the JavaScript. That's what you proposed and that is completely fair to do. It's isn't a hack. It should be one variable with a JSON string.
Cookie:
Put the data into a temporary cookie delivered with the page and read the cookie from JavaScript. This is cleaner than the variable solution, but isn't the simplest way.
HTML injection:
There is one other possibility for using #Model, instead of injecting the JSON string into a JavaScript variable, which requires injecting JavaScript tags too, put it into a property on an HTML element and then access the property from JavaScript. This is simpler and my preferred method. Property names beginning with "data-" are designed for this.

Take C# const from backend and use it in JS file?

I have one tricky question.
Is there a way to take C# const and use it in .JS script with Jquery ?
This is how const look:
public class UserRoles
{
public const string Read = "Read";
public const string ReadWrite = "ReadWrite";
}
It depends a bit of what you are trying to do with those values.
You could place the values in a js object when your UI initializes (ex: window.YourAppName.Constants.Read = "your C# constant" in Index.html). Then you could load your jquery script and make use of the constant values once the document finished loading.
Alternatively, if you are using MVC, you can make use of tags within your views, and thus have access to C# code (viewmodel, enums, etc.). However, if you have lots of js code then it would be best to keep that in js files and in such a case I would go for the first option.
You can't use Razor in JavaScript files, you would have to have the variable passed to a razor view in the viewbag/data or model.
Then in the shared layout you could create a javascript function that returns this variable, then in your .JS file you could call that function to get the variable as long as it is loaded after.

Use TAL:defined variable in javascript

I'm creating a page template for a plone-based website. I've defined some variables using the template attribute language:
<tal:macro metal:define-macro="sample" tal:define="var python: here.getThisVar();">
Now I would like to use var in an extern javascript file, that I call by clicking a button inside my template. How can I transfer my variable, that I can work with it in my javascript file?
In your template define a javascript variable by writing it out using TAL like this:
<script type="text/javascript" tal:content="string:var MY_VAR=${view/myVar};"></script>
Now MY_VAR should be available in scope of your external js as long as you call it after the line above...
Another way: inject your variable into HTML using an HTML 5 data attribute::
<div id="myVar" tal:attributes="data-myVar python:here.getThisVar();">
Then read it using JAvaScript/jQuery::
$('#myVar').data('myVar');
There are a variety of ways to do it. All involve constructing Javascript code as if it's text, then returning the result for insertion into a page or rendering as a JS resource in the javascript registry.
If you'd like a robust example that includes provisions for message translatability and works with the JS resource registry, see the way Plone itself does it: https://github.com/plone/Products.CMFPlone/blob/4.2.7/Products/CMFPlone/browser/jsvariables.py

Redefining a RequireJS module -- is it possible?

Basically, there is a page that I visit that uses RequireJS. I want to make adjustments to this page, so I went the route of a userscript. While looking at the client-side code I see that there is a module defined as so:
define("settings", [], function() {
return {
SETTINGA: "100",
SETTINGB: "200",
etc.
}
})
I want to add my own item to the settings array, as well as change some settings without having to redefine the module in my userscript (with the changes) and then removing/readding it. Is it possible to just make adjustments to this module?
P.S. I'm using the Script Injection technique to get my userscript to interact with other javascript in the original page.
Also, doing require("settings") in the Javascript console returns an object (not an array), so I can't do things like require("settings")[0] or require("settings").push(...), however I can access the settings by doing require("settings").SETTINGA. So, I'm not sure how to add/redefine settings to this since it is not an array?
Use this:
require('settings').new_property = 'new value';
The reason you can't retrieve or add settings to "the settings array" is that you aren't creating an array to begin with. {foo:bar} is an object literal, not an array literal ([foo,bar]).

Best Practice for Storing JSON Data That Will Be Passed to jQuery Plugin

I'm looking for the "best practice" as to where the JSON should be stored if it's just a string array. Should it be stored in a variable in a script block in the HTML page? Should it be stored in a JavaScript file outside of the HTML for separation? Or should it be stored in the plugin itself?
If it should be an external js file, what's the "best practice" naming scheme for the file? I know the accepted jQuery plugin name is jquery.plugin.js or jquery.plugin-min.js (for the minified file).
Depends, if you need the JSON right away you can store it anywhere to get it executed:
<script> var myJsonObj = { ... }; </script>
If it's a lot of Data and you don't need the data right away, you can always make an ajax call to a file named something like "data.json".
For naming the plugin name, well it's really up to you, but yeah I believe jquery.pluginname.js is the standard way of doing it.
I'll second sktrdie to add the extension .json for a file like this. A gotcha that I ran across when first playing with JSON is that a JSON string is not a valid JavaScript File.
For example, If I call a file with this content:
{
'foos': 'whatever',
'bar': false,
'items': [1,2,3]
}
as the src of a <script> tag, I get this error:
Error: invalid label
Line: 2, Column: 1
Source Code:
'foos': 'whatever',
In the past I've actually hidden JSON strings in <divs> or spans like this:
<div id="jsonStorage" style="display:none">
{'foos': 'whatever','bar': false,'items': [1,2,3]}
</div>
I've also used hidden form fields for this.
If it's part of the plugin, i.e. default config, I'd store it in the plugin file itself. If it's an external config for the plugin, then it depends. It might make sense to store it in a variable in the HTML, i.e.
<script>
var myConfig = {
"foo" : "bar"
};
</script>
This could especially be the case if you need any of the JSON to be generated by your back-end code.
Really, the answer is "it depends" -- can you give more details?

Categories

Resources