I have an asp.net app with a site.js which is getting lengthy. What is the proper way to architect the file structure so that /home routes will load a home.js file and /product routes will load a routes.js file?
Ideally I would like to keep all the js files in the wwwroot folder and not next to the views or within them so I can minify them with the compiler
you can create an extension method for Html helper and call that on _Layout.cshtml as #Html.RenderControllerJs(Url); so that it gets called every time and inject the respective js.
public static class HtmlHelperExtentions
{
public static IHtmlContent RenderControllerJs(this HtmlHelper html, UrlHelper urlHelper)
{
var env = html.ViewContext.HttpContext.RequestServices.GetService<IHostEnvironment>();
var controllerName = html.ViewContext.RouteData.Values["Controller"].ToString().ToString();
var jsFileRelativePath = Path.Combine("<folder_path_for_all_controller_js>", $"{controllerName}.js");
var controllerJsFilePath = Path.Combine(env.ContentRootPath, jsFileRelativePath);
if (File.Exists(controllerJsFilePath))
{
return html.Raw(
$"<script type=\"text/javascript\" src=\"{urlHelper.Content(Path.Combine("~", jsFileRelativePath))}\"></script>");
}
return new HtmlString("");
}
}
You can also write custom logic specific to any controller. You have full control now.
Related
I'm new to ASP.NET MVC. After reading many different examples I still can't get this done.
I have some JS scripts bundled and one out of the bundle (because I'm using a different main script per page)
(_Layout.cshtml)
#Scripts.Render("~/bundles/modernizr")
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/datatables")
#RenderSection("scripts", required: false)
And in my view
(index.cshtml)
#section Scripts
{
<script src="#Url.Content("~/Scripts/index.js")"></script>
}
In javascript code I am trying to call a specific URL of my application
(index.js)
$('#table').DataTable({
ajax: '#Url.Action("List", "Documents")'
});
Of course in my application a controller is definend with the name DocumentsController and with a List method, returning the correct JSON.
Still it seems no-one is ever replacing my url
If I include my index.js in the bundle, nothing changes.
Where is the mistake?
Who and when is replacing that URL?
Thank you
You can't use Razor code inside a *.js file because they're served directly as static files and aren't processed by ASP.NET (nor *.ts files because they're transpiled to *.js at build-time).
What you can do instead is to render Razor-generated JavaScript in your View/Page and have your TypeScript or JavaScript expect that data to be available.
Like so:
Index.cshtml
<script type="text/javascript">
var scriptUrls = {
listDocuments: '#Url.Action("List", "Documents")';
};
</script>
Index.ts (if using TypeScript)
interface PageUrls {
readonly listDocuments: string;
};
declare var scriptUrls: PageUrls;
//
$('#table').DataTable({
ajax: scriptUrls.listDocuments
});
Index.js
$('#table').DataTable({
ajax: scriptUrls.listDocuments
});
I need to call a function from external js file into my Angular component
I already go through the related question
How can i import external js file in Angular 5?
How to include external js file in Angular 4 and call function from angular to js
My External JS (external.js)
var radius = 25;
function calculateRadius(pi) {
let piValue = 3.14159;
if(pi) {
piValue = pi;
}
var result = piValue * radius * radius;
console.log('Result: ', result);
}
function wrapperMethod(pi) {
console.log('Hi, this is from wrapper method');
calculateRadius(pi)
}
I added the said JS file in the angular.json under scripts block
"scripts": [
"src/assets/external.js",
]
In the CircleComponent, I would like to call the method
import wrapperMethod from '../../src/assets/external.js';
#Component({
selector: 'app-circle',
templateUrl: './circle.component.html',
styleUrls: ['./circle.component.css']
})
export class CircleComponent implements OnInit {
constructor() { }
ngOnInit() {
wrapperMethod(3.14159);
}
}
But its failing to call the method. Kindly assist me how to achieve this.
Note: The said methods as just an example methods, I want to implement this logic with the complex code file. The said question tells about typings.d.ts, but I don't know where is typings.d.ts in my Angular project. Kindly brief me regarding this. If the said question gives good solution means, why should I post this question.
Angular Structure (Created using Angular CLI)
I don't know where is typings.d.ts, could anyone please tell me where is typings.d.ts - which is mentioned in the said questions How to include external js file in Angular 4 and call function from angular to js
You can follow this below steps
1) First add a reference of your external JS file for importing it to the component.
import * as wrapperMethods from '../../src/assets/external.js';
2) Now declare a "var" of the same name that your function has inside external JS.
declare var wrapperMethods: any;
3) ngOninit(){
wrapperMethods();
}
put your external .js file under scripts in build
if still can not see methods inside it put in in index.html
<script src="assets/PATH_TO_YOUR_JS_FILE"></script>
in your component after import section
declare var FUNCTION_NAME: any;
ANY_FUNCTION() {
FUNCTION_NAME(params);
}
Don't get confused with typings.d.ts. Follow below steps.
1.Add your external file inside assets folder. The content of this file will be by default included as per your angular-cli.json.
2.The function of your js which you're going to use must be exported. i.e.
export function hello() {
console.log('hi');
}
3.Import your file inside your component as below.
import * as ext from '../assets/some-external.js';
4.Now you can reference it like
ext.hello();
Steps:-
1. create a external js file.
2. In component.ts use the below code.
ngOnInit() {
this.loadJsFile(JsFilePath);
}
public loadJsFile(url) {
let node = document.createElement('script');
node.src = url;
node.type = 'text/javascript';
document.getElementsByTagName('head')[0].appendChild(node);
}
3. If u use jquery then define selector in html to render. Or store data in variable.
Make sure you have to add jquery cdn in index.html and you have to install Jquery and its types package from npm.
Yii::app()->getClientScript()->registerCssFile(Yii::app()->theme->baseUrl.'/css/jquery.ad-gallery.css');
Yii::app()->getClientScript()->registerScriptFile(Yii::app()->theme->baseUrl.'/js/jquery.ad-gallery.js', CClientScript::POS_HEAD);
I want to load these files only for one particular view
Or any better idea to import CSS and Javascript in Yii framework for a particular view
Like so:
public function actionIndex()
{
$uri = 'path to your action-specific css';
Yii::app()->clientScript->registerCssFile($uri, 'screen, projection');
}
and like this, if you want controller-specific files:
public function init()
{
$uri = 'path to your controller-specific css';
Yii::app()->clientScript->registerCssFile($uri, 'screen, projection');
return parent::init();
}
If you want this functionality on all controllers, create a subclass of CController, put these methods in there, and change your controllers to use the new subclass.
This will help you definitely
I'm using VS2015 with Gulp and I'm trying to build AngularJS with TypeScript.
In my index.html, I have a script tag to my "app.js" (the output and bundle of the TS build).
However if I want to reference my controller, and any other services - how can I avoid having to put the relevant script tags in each and every HTML file - is there a way I can just reference the app.js file and be done with it? What's the recommended approach?
Cheers,
if you want to refrence only one file in html via script tag and other files just reference in other js files then you can use requirejs. It is a nice tool to load scripts. in production it is a good approach to concat and minify all your scripts to reduce number of requests.
I managed to resolve it using experimental typescript decorators, requirejs and a little of imagination.
So, in resume I wrote two decorators one called AppStartup and other called DependsOn. So at angular bootstrap I can get and register all dependencies.
I ended up with something like it:
TodoListController.ts
import {DependsOn, AppStartup, ngControllerBase} from "../infra/core";
import {taskManagerDirective} from "../directives/TaskManagerDirective";
#AppStartup({
Name: "TodoSample"
}).Controller({
DependsOn: [taskManagerDirective]
})
export class TodoListController extends ngControllerBase {
public ByControllerAs: string;
constructor() {
super(arguments);
let $httpPromise = this.$get<ng.IHttpService>("$http");
$httpPromise.then(function ($http) {
$http.get('http://www.google.com').success(function (body) {
console.info("google.com downloaded, source code: ", body);
});
});
this.ByControllerAs = "This was included by controllerAs 'this'";
}
}
rowListItemDirective.ts
import {DependsOn, ngDirectiveBase} from "../infra/core";
import {rowListItemDirective} from "./RowListItemDirective";
#DependsOn([rowListItemDirective])
export class taskManagerDirective extends ngDirectiveBase{
public template: string = `
Parent Directive
<table>
<tbody>
<tr row-list-item-directive></tr>
</tbody>
</table>
`;
}
You can see what I did below at my github repository:
https://github.com/klaygomes/angular-typescript-jasmine-seed
i had my web app and cordova mobile app running now on angular 1 for about 2 years now, as application grow bigger we wanted to migrate our next version of app to angular 2.
current project is structured like following
----/root
|__app
|____app.js
|____app.css
|____index.html
|____app.common.directives.js
|____app.common.services.js
|____Page1
|______Page1.js
|______Page1.css
|______Page1.service.js
|______Page1.html
|____Page2
|______Page2.js
|______Page2.css
|______Page2.service.js
i had gulp building my app like so
it concat all js files into build/build.min.js
it concat all css files into build/build.min.css
cache all html in app folder and append it to build.min.js using templateCache (angular1)
copy index.html from app folder to build folder.
run watch server root # /build
This setup was very useful for us since when ever we are working on a new Module (a page essentially) all we have to do is create a new folder, drop a js and html file, and we are done !
example Page1.js
angular.module('mainApp')
.config(function($httpProvider, $stateProvider) {
$stateProvider.state('Page1', {
url: '/Page1',
controller: 'Page1Ctrl',
controllerAs: 'Page1',
templateUrl: 'Page1/Page1.html'
});
}).run(function($rootScope) {
$rootScope.sideMenu.push({
link: 'blog',
title: 'Announcements',
icon: 'bullhorn',
sideMenuOrder: 1
});
})
.controller('BlognewPost', function($server, $http, $scope,$state) {
var self = this;
this.method1 = function(){};
this.var1 = 'Hello Angular';
});
as you can see every module define its own routes, add it self to $rootScope.sideMenu -which is used in index.html to show sidemenu- and defines its own controller.
and our app.js was the main app file which wire connect modules/pages together, yet it was important to keep app.js un aware of how many pages/routes our app has.
angular.module('mainApp',['ngAnimate','ngMessages', 'ngAria'])
.config(function() {/*...*/})
.run(function($rootScope) {
$rootScope.sideMenu = [];
});
index.html is something like.
<html>
<ul id="side">
<li ng-for="item in $root.sideMenu" ui-sref="item.link">...</li>
</ul>
<ui-view id="content"></ui-view>
</html>
Question:
now with new angular2 component structure. is there a way we can migrate our old app while keeping same structure and build system ?
is it possible to define all routes in the components without root component have any knowledge of its existence ? -in above example you can see when ever we needed to add a page, we never touch app.js, we just create a new folder, and add the config, routes, run, and controller in its own folder.
our app is composed of 16 root pages making around 500k character compressed. should we rewrite the whole thing at once, or is there a way to migrate page by page ?
i see in angular2 starter component takes templateUrl config to point to template, is there a way to make typescript include the templateUrl html file as a string 'behavior like what templateCache used to do in angular1' ?
#Component({
selector: 'my-app',
template: string // OR templateUrl: 'page.html'
//what i need is something like template: require(page.html) so that my app html would be cached in js.