Object paths in javascript - javascript

I have an asp.net boilerplate project. I am trying to create a form and write it into database. I have a Index.cshtml file and Index.js file. I cant create object of c# class in javascript. It says "MyProject" is undefined.
var requestService = MyCompany.MyProject.Requests.RequestService;
is this valid?
What is the syntax of Paths in javascript?
Is it possible that creating an object in cshtml file and passing it to javascript file?

Alas, this is not how you do it. The js is client side only, and isn't aware that the .net code exists.

So, in ASP.NET Boilerplate there are services that we use in controllers. This services can be used in JavaScript file such as
var _tenantService = abp.services.app.tenant;
In view (cshtml) when we click on submit button, form is being sent to app services.
_$form.find('button[type="submit"]').click(function (e) {
e.preventDefault();
if (!_$form.valid()) {
return;
}
var tenant = _$form.serializeFormToObject();
abp.ui.setBusy(_$modal);
_tenantService.create(tenant).done(function () {
_$modal.modal('hide');
location.reload(true); //reload page to see new tenant!
}).always(function () {
abp.ui.clearBusy(_$modal);
});
});
And if we want to add new services or add new methods to services, we have to use camel notation in javascript files. Otherwise it says undefined. For example: I created a method named "NewCreate". I had to call it like "newCreate".
But I still don't know how Javascript accesses to "abp.services.app.tenant;"

Related

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.

Javascript code organization data driven application

I'm currently working on the front-end of a medium/large-scale data-driven Asp.net MVC application and I have some doubts about the right code-organization/design pattern to follow.
The web application is made by multiple pages containing many Kendo UI MVC widgets defined with Razor template.
For those who are unfamiliar with Kendo, the razor syntax is translated to Javascript as the following snippet:
I defined inside my Script folder two main folders, and I structured my js files as follow:
shared //Contains the shared js files
-file1.js
-file2.js
pages //One file per page
page1.js
page2.js
...
Ticket.js // page 4 :)
Each js file is a separate module defined with the following pattern:
Note: Inside init function is registered every callback function to the window events and occasionally a $(document).ready(function(){}) block.
;(function () {
"use strict";
function Ticket(settings) {
this.currentPageUrls = settings.currentPageUrls;
this.currentPageMessages = settings.currentPageMessages;
this.currentPageEnums = settings.currentPageEnums;
this.currentPageParameters = settings.currentPageParameters;
this.gridManager = new window.gridManager(); //usage of shared modules
this.init();
}
Ticket.prototype.init = function () {
$("form").on("submit", function () {
$(".window-content-sandbox").addClass("k-loading");
});
...
}
Ticket.prototype.onRequestStart = function (e) {
...
}
//private functions definition
function private(a, b, c){
}
window.Ticket = Ticket;
}());
Once I need my Javascript functions defined in a module I include the associated Javascript file in the page.
An istance of my object is stored inside a variable and, on top of that, a function is bound to the widget event (see: onRequestStart).
HTML/JAVASCRIPT
#(Html.Kendo().DropDownList()
.Name("Users")
.DataValueField("Id")
.DataTextField("Username")
.DataSource(d => d.Read(r => r.Action("UsersAsJson", "User"))
.Events(e => e.RequestStart("onRequestStart"))))
var settings = {};
var ticket = new window.Ticket(settings);
function onRequestStart(e){
ticket.onRequestStart(e);
}
I feel like my design pattern might be unfriendly to other front-end delevoper as I am, mostly because I choose not to implement the Javascript modules within Jquery plugin.
First, Am I doing everything the wrong way?
Second, is my design pattern suitable for a Javascript test-framework?
Third, which are the must-have scenarios for Jquery plugins?
Update
Added the Javascript output by the above Razor syntax.
Folder structure
In terms of functionality (shared) and modules (modular approach), the development or application code should represent what you can encounter in HTML. A simple ctrl+f over your solution should yield all possible changes. From that experience over the years I personally prefer dividing it in:
app (application code)
classes (reusable)
modules (singleton)
lib (package manager/grunt/gulp/...)
jquery (proper library names/unminified dist file or root file)
kendo
File names
Representing what something does and to be able to reuse it in a blink of an eye is what will cut your development time. Choosing proper names has value as I'm sure you are aware. My file names always starts with the namespace usually in short followed by a reusable "search" term:
app/prototypes
ns.calendar.js (multiple configs)
ns.maps.js (combinations or single uses)
ns.places.js (forms or map add-ons)
ns.validation.js (multiple forms and general handling)
app/singletons
ns.cookiebox.js (single config)
ns.socialmedia.js (single config)
ns.dom.js (provides a place for dom corrections, global resize events, small widgets, ...)
To add, what you called shared, is functionality that's meant to be global. A great example would be to use underscore library. Or create a collection of functions (device detection, throttle, helpers in general) on your own to reuse throughout projects => ns.fn.js
Since you add them only once throughout your namespace, it's also built as singleton and can be added to the modules folder or directly in the app root.
As last addition a loader file to kickstart your point of control => ns.load.js in the app root. This file holds the single DOM ready event to bind protoypes and modules.
So you might want to rethink your idea of dividing into pages. Trust me, I've been there. At some point you'll notice how functionality grows too large in order to configure all pages separately and therefor repeatedly.
File structure
To be honest I like Tip 1 of #TxRegex answer the most, with a small addition to bind the namespace and pass it from file to file as it get's loaded.
Core principle: IIFE bound to window object
window.NameSpace = (function($, ns){
'strict'
function private(){}
var x;
ns.SearchTerm = {};
return ns;
}(window.jQuery, window.NameSpace || {}));
For more example code I'd like to point out my github account.
Bundling
Try to achieve a single bundled and minified file from lib to app, loaded in the head on async for production releases. Use separated and unminified script files on defer for development and debug purposes. You must avoid inline script with global dependencies throughout the whole project if you do this.
path to js/lib/**/*.js (usually separated to keep sequential order)
path to js/app/ns.load.js
path to js/app/ns.fn.js
path to js/app/**/*.js (auto update the bundle)
Output => ns.bundle.js
=> ns.bundle.min.js
This way you'll avoid render blocking issues in JavaScript and speed up the loading process which in turn boosts SEO. Also enables you to combine functionality for mobile layouts and desktop layouts on the fly without memory issues or jerky behavior. Minifies really well and generates little overhead in calling instances from the loader file. As a single bundle will be cached throughout your pages it all depends on how many dependencies or libraries you can cut from the bundle. Ideally for medium and large projects where code can be shared and plugged in to different projects.
More info on this in another post.
Conclusion
First, Am I doing everything the wrong way?
Not at all, your modular approach seems ok...
It's missing a global namespace, which is hard to avoid without at least one. You create one for each module but it seems better to group them all under one namespace so you can differentiate library code from application code in the window object.
Kendo seems to create inline scripts? Can't you counter the placement server side?
Second, is my design pattern suitable for a Javascript test-framework?
Except for the Kendo instances, you can add a layer for testing purposes. Remember if jQuery is your dependency inline, you'll have to render block it's loading. Otherwise => jQuery is undefined
Exclude Kendo dependencies from the bundle if you can't control the inline script. Move to a </body> bundled solution.
Third, which are the must-have scenarios for Jquery plugins?
modular approach
configurable approach for multiple instances (tip: moving all strings from your logic, see how Kendo uses object literals)
package manager to separate the "junk" from the "gold"
grunt/gulp/... setup to separate scss and css from js
try to achieve a data-attribute binding, so once all is written, you configure new instances through HTML.
Write once, adapt easily where necessary and configure plenty!
The organization and pattern seems fine, but I have some tips:
Tip 1:
Instead of setting specific global variables within your module, perhaps you could return the object instead. So instead of doing this:
;(function () {
"use strict";
function Ticket(settings) {
console.log("ticket created", settings);
}
...
window.Ticket = Ticket;
}());
You would do this:
;window.Ticket = (function () {
"use strict";
function Ticket(settings) {
console.log("ticket created", settings);
}
...
return Ticket;
}());
The reason for this is to be able to take your module code and give it a different global variable name if needed. If there is a name conflict, you can rename it to MyTicket or whatever without actually changing the module's internal code.
Tip 2:
Forget Tip 1, global variables stink. Instead of creating a seperate global variable for each object type, why not create an object manager and use a single global variable to manage all your objects:
window.myCompany = (function () {
function ObjectManager(modules) {
this.modules = modules || {};
}
ObjectManager.prototype.getInstance = function(type, settings) {
if (!type || !this.modules.hasOwnProperty(type)) {
throw "Unrecognized object type:";
}
return new this.modules[type](settings);
};
ObjectManager.prototype.addObjectType = function(type, object) {
if (!type) {
throw "Type is required";
}
if(!object) {
throw "Object is required";
}
this.modules[type] = object;
};
return new ObjectManager();
}());
Now each of your modules can be managed with this single global object that has your company name attached to it.
;(function () {
"use strict";
function Ticket(settings) {
console.log("ticket created", settings);
}
...
window.myCompany.addObjectType("Ticket", Ticket);
}());
Now you can easily get an instance for every single object type like this:
var settings = {test: true};
var ticket = window.myCompany.getInstance("Ticket", settings);
And you only have one global variable to worry about.
You can try separating your files in different components asuming each component has a folder.
for example: page 1 is about rectangles so you make a folder call rectangle inside that folder you create 3 files rectangle.component.html, rectangle.component.css, rectangle.component.js (optional rectangle.spec.js for testing).
app
└───rectangle
rectangle.component.css
rectangle.component.html
rectangle.component.js
so if anything bad happends to a rectangle you know where is the problem
a good way to isolate variables and execute in the right place is to use a router basically what this does it check at the url and executes the portion of code you asign to that page
hope it helps let me know if you need more help.

What is the standard workaround for dynamic js files

Is there a standard workaround for something like this in ASP.NET:
//myinclude.js
$(document).ready(function() {
for(recs=0; recs < {{server-side-value}}; recs++) {
// process records
}
});
Note this is a js file. I know about WinForms ability to insert dynamic quoted scripts into the page. But how about a page's js file that is dependent on server-side values? I know you can use something like:
//myview.cshtml
var instance = new MyObject(<%= ServerSideValue =%>);
and include it on the page to pass it to the js file, but I'm wondering about the architecture of keeping js separate from html code so that an html/css designer can work with the template free of javascript; keeping everything separate. I primarily use MVC now.
What are some of the patterns to deal with this? Is the only solution dynamically inserting js into the actual page or having partial views included separately into the page.? Or is there a way to sprinkle server-side values in separated js? In short, no dynamic js files?
I'm not trying to fix an exact project at this time, I have just been curious about this on past projects.
Thanks...
There are multiple ways to achieve this. One of the ways would be populating your data into a Javascript objects on the HTML page directly.
//myview.cshtml
<script>
var pageData = {
name : '#variable1',
value1: #value1
};
</script>
And, in the javascript file:
//pageUI.js
if (pageData) {
$('#page_tile').html(pageData.name);
}
I am sure you can optimize a whole lot (for example, having a single communication between the server side data and the client side code). At the end of the day, you want to make sure that your javascript code can be resusable.
for example one can do this:
A. have the main .js code read any context-specific parameters from the current window like this (page.js):
!function(window){
var configData = window.MyAppNameConfigData;
// rest app code here..
}(window);
B. the server side script can inject these context-specific data in the page's html like this:
<script>
window.MyAppNameConfigData = {
param1: //..
param2: //..
// etc..
};
</script>
Note if needed make sure that the page.js is enqueued/loaded after the data have been injected/inserted (using a script dependency chain for example)
If it's not "inline" (on the View/Page itself), you could do a Partial View/Page:
Trivial example: _PartialJs.cshtml
$(document).ready(function() {
var foo = "#DateTime.Now.Year";
});
Then in your view:
<script>
#Html.Partial("_PartialJs")
</script>
Renders:
<script>
$(document).ready(function() {
var foo = "2015";
});
</script>
Hth...

Call an external .js file javascript function without a long parameter list

I have two MVC Razor views (.cshtml) that have a virtually identical Javascript function within them.
In order to de-duplicate my javascript code I want to extract the Javascript from the views to a single external Javascript file (.js) containing the function (with a parameter that can be used to differentiate the minor differences need for each view).
The Javascript in the views contains Razor syntax to access many asp.net resource file (.resx) text values (e.g. var foo = '#ResourceFileName.Bar';) which the Razor engine unfortunately does not parse for me.
To overcome this I could pass all the resource file text values to the function in the .js file as parameters – but I prefer not to do that as the parameter list would become very large.
The RazorJS package (http://www.nuget.org/packages/RazorJS) will allow me to use Razor syntax within a .js file but this package was last published way back in 2011, which worries me.
What techniques could I use to call the externalised function without a huge long parameter list ?
What techniques could I use to call the externalised function without
a huge long parameter list ?
It doesn't need to be a huge parameter list. A single parameter containing all the necessary resource properties will be enough:
<script>
var args = #Html.Raw(Json.Encode(new
{
foo = ResourceFileName.Foo,
bar = ResourceFileName.Bar,
baz = ResourceFileName.Baz
}));
myFunction(args);
</script>
and then in your function you can access all those properties:
function myFunction(args) {
// you can use args.foo, args.bar and args.baz here
}

How do you call a JavaScript function that is in an embedded resource for an ASP.Net Custom control on the page that the control is hosted?

I have an html editor custom control that I've been working on that has a basic undo/redo function that works well with all the functions that are part of the editor. The undo/redo function works off of 2 stacks (respectively named UndoStack and RedoStack), which when one of the other editor functions that modify the text property of the editor occur push on to the UndoStack. For visualization, when Undo is clicked, pop is called and that value is stored to the redo stack.
However, the editor also interacts with some on-page AJAX functions that allow the user to insert already written text stored in our database. What I want to accomplish here is to include the the JavaScript that is used to run the editor on the page and call the functions needed to push text on to the undo stack from the page.
As a side note, I used the solution provided by Rob2211 on Embedded dll resources to get the script file on the page in question, but I would like to know how to call a function from it as it keeps saying that the function I want to call (pushUndoStack(), excuse the lack of creativity) is undefined.
Thanks
P.S. I generally code in C#, but some of the project is in VB.NET
Code Snippets: On Page
Register Page Directive
<%# Register Assembly="WebControl.HtmlEditor" Namespace="WebControl.HtmlEditor" TagPrefix="ec" %>
Code that grabs the HtmlEditor.js function
<script type="text/javascript" src="<%= HtmlEditor.Resource.GetClientScript(Me.Page, "HtmlEditor.js")%>"></script>
Code Snippets: In C# file
The Resource Class
public class Resource
{
public static string GetClientScript(Page p, string file)
{
return p.ClientScript.GetWebResourceUrl(typeof(Resource), typeof(Resource).Namespace + ".Scripts." + file);
}
}
The assembly reference:
[assembly: WebResource("WebControl.HtmlEditor.Scripts.HtmlEditor.js", "text/javascript")]
The Prototype function: (Contains the following undo/redo functions)
WebControl.HtmlEditor.HtmlEditor.prototype =
{
.
.
.
}
From the Embedded JavaScript File: All undo/redo related functions.
getUndoStack: function () {
return this.undoStack;
},
pushUndoStack: function (value) {
this.undoStack.push(value);
},
popUndoStack: function () {
return this.undoStack.pop();
},
getRedoStack: function () {
return this.redoStack;
},
setRedoStack: function (value) {
this.redoStack = value;
},
clearRedoStack: function () {
var redoStack = this.getRedoStack();
redoStack = new Array();
this.setRedoStack(redoStack);
},
pushRedoStack: function (value) {
this.redoStack.push(value)
},
popRedoStack: function () {
return this.redoStack.pop();
}
I solved this using jQuery. Since the JavaScript function I needed was embedded in the HTML Editor custom control, the function that I needed was already available to the page, it just needed to a way to get to it. Using the $find('ControlID') method, I was able to search the DOM tree for the ID of 'Editor' and access everything that was included with the control, in this case, the function called pushUndoStack(). What lead me to this conclusion was a another part of this project that did the spell checking component of this project.
Thanks to #AndrewWalters and #TsanyoTsanev for the help.

Categories

Resources