Angular cli: include angularjs component styles in ngUpgrade hybrid project - angularjs

Now I'm moving to a hybrid angular/angularjs project. But I stuck with import styles problem.
For example, my simple angularJs component:
import template from './simple.html';
import controller from './simple.controller.js';
import './simple.less'; // <-- Look at
export const SimpleComponent = {
template,
controller
};
I expect that styles will be extracted and included in the project.
Before I switched to the angular-CLI all magic works because of 'MiniCssExtractPlugin'.
If I create angular components:
#Component({
selector: 'app-simple',
templateUrl: './simple.html'
styleUrls: ['./simple.less']
})
All styles add correct. The same, if I it with angular.json ->
(path) projects.projectName.architect.build.options.styles
"styles": [ "src/assets/styles/index.less" ]
Now I suggest 2 ways to solve the problem (first doesn't work, second will be in a pinch):
1) Add "extractCss":true rule in angular.json -> projects.projectName.architect.serve.options. But it doesn't work.
I create issue on github about "extractCss" option.
But maybe I don't understand what exactly "extractCss" option means, and delegate 'MiniCssExtractPlugin' plugin functionality to it?
2) Create 'app.less' in 'src/app' folder and add all component styles to it. After that include it to 'angular.json' -> "styles": ["src/app/app.less"]. But it takes a lot of overhead because we have a lot of components =)
Thank you for attention =)

Related

Change detection not working in downgraded Angular components

I'm in the process of converting a rather big application written in AngularJS to an Angular application using the #angular/upgrade module. For now, every component from AngularJS is running as expected in the Angular app. The app is being bootstrapped like this:
export class AppModule {
constructor(
private upgradeModule: UpgradeModule,
) {}
ngDoBootstrap() {
this.upgradeModule.bootstrap(
document.body,
['myApp'],
{ strictDi: true },
)
}
}
However, I've started to rewrite components in Angular and I've run into problems trying to get those downgraded components to work. I'm using ui-router to map components to states like this:
function config($stateProvider) {
$stateProvider.state('some-state', {
parent: 'app',
views: {
content: {
component: 'someComponent'
}
},
url: '/some-state'
})
}
The rewritten component is being downgraded like this:
angular
.module('myApp')
.directive(
'someComponent',
downgradeComponent({ component: SomeComponent }),
)
SomeComponent is just a regular Angular component.
It shows up fine, the template is being rendered and everything, however, change detection doesn't seem to be working. The change detector seems to run once shortly after the view is being rendered, after that however, it doesn't ever run again unless i call it manually. NgZone.isInAngularZone() returns false if run anywhere within the downgraded component, I'm not sure if this is intended or not. If I inject ChangeDetectorRef and run detectChanges on any methods that change the fields of the component, the updates are being detected and rendered just fine. However, it would be way too much work in the long run to append an (input)="changeDetectorRef.detectChanges()" to every input, and call detectChanges() in pretty much any function that does anything.
Is there anything I am missing? If I haven't provided enough information, I can try to get a minimal reproduction of the problem running, this would probably be a bit of work though, so I want to ask like this first.
Ok, so the answer turned out to be something really simple. While I upgraded everything individually, I copied over most of the old index.html, which still contained ng-app="myApp" on the body tag.
This caused the AngularJS app to bootstrap itself in the HTML instead of the Angular app handling the bootstrapping, which prevented the AngularJS app from running in the NgZone. I'm leaving this here for anyone who makes the same mistake. In short, make sure you've removed the old ng-app-tag from your index.html.

Import angularjs modules with webpack

We've got a rather large project written in angularjs and are moving gradually to angular 4. The plan is to first rewrite everything to typescript + angularjs components. We've set up an empty angularjs+webpack+typescript project and are converting legacy angularjs modules to typescript. This works fine, but because of the size of the project we would like to add the 'old' angularjs modules for now and execute those scripts so we have a full working project.
I haven't found a way to make this work. So basically we've got (I've omitted some details for brevity):
app.module.ts:
import * as angular from 'angular';
import { moduleName as module1 } from './app/converted.module1';
import { moduleName as module1 } from './app/converted.module2';
export const moduleName =
angular.module('application', [
module1,
module2,
'legacy_module_3',
'legacy_module_4'
]).name;
So module1 and module2 are already converted typescript modules. Module 3 and module 4 not. We don't want to convert those yet but do want to reference them. Lets say those modules reside in '/frontend/module3.js' and '/frontend/module4.js', how would I make this work (executed js code) with webpack?
Consider just biting the bullet and doing minimal conversion on everything in one go.
I just went through a similar exercise converting an existing angularjs project to use webpack. The conversion needed for each module is small enough that I just converted all of the modules. So where we had:
angular.module('somemodule').controller(function(){ ... })
I changed those to:
export default function SomeController() { ... }
and the module declaration files all now look like:
import SomeController from './some.controller'
export default angular.module('SomeModule', [])
.controller(SomeController)
.name;
Then the top level:
import SomeModule from './some/module'
angular.module('app', [ SomeModule ]);
It took a little while, but as the changes are largely mechanical I was able to just work systematically through the entire application. Some sub-folders were just using the 'app' module name, so I added a 'module.js' file in each folder with an appropriate module name, but otherwise there weren't any real changes to be made.
I also had to change all of the template urls into imports and I imported the '.scss' file into the top level of the app (though that wasn't really required).
Next step will be to convert controllers and directives to components, but that should be pretty straightforward now.
You've got to export each one of your modules and then import them in your app module. Notice the following example:
//..import your other ts modules
import module3 from './frontend/module3.js' //This have to be relative path
import module4 from './frontend/module4.js'
export const moduleName =
angular.module('application', [
module1,
module2,
module3.name ,
module4.name
]).name;
Also notice that your old js modules should export a module:
e.g. filters module.
import angular from 'angular';
import myNiceFilter from './myNiceFilter.filter';
var filters = angular.module('filters',[]);
filters.filter('myNiceFilter', myNiceFilter);
export default filters;

Import dynamically generated script from html file with webpack 2

I'm in the process of migrating to webpack using typescript and I have some script dynamically generated into my index.html like so
<script>(function(modules) { code inside ... })</script>
How would I import code (pretty straight compiled typescript to javasript code) from this script into my main.ts file (the entry point)? For example
import whateverFunction from 'index.html'
Of course that doesn't work but I would love to see the right way to implement it. Thanks in advance.
If you defined a variable on index.html and you want to use it in typescript you need to do this:
declare var prod: boolean;
declare var version: string;
export class whateverName{
}
you should use the same name that used in index.html file.

AngularJS libraries conflicting with each other

I'm using gulp to combine my scripts in order to load only one file in HTML (make it faster).
Here's a sample code, name of libraries don't matter much, you'll get the idea :
// gulpfile.js
mix.scripts([
'vendor/jquery-2.1.1.min.js',
'vendor/angular.js',
'vendor/slideout.min.js',
'vendor/dirPaginate.js',
'vendor/cookie.js'
], 'public/js/libs.js');
And then I do this :
// app.js
let app = angular.module('app', ['angular-slideout', 'cookie', 'dir-paginate'], function ($interpolateProvider) {
$interpolateProvider.startSymbol('<%');
$interpolateProvider.endSymbol('%>');
});
export default app;
I only use one file to load every NG library in my project, and then I import this app in my controllers. Now this is only an example, but I already have conflicts depending on the order of mixing these scripts in.
Any advice on processing this ? I already had to ditch some libs I wanted to use because they were conflicting with others. Going on this way, this looks like a dead end.

How to make custom theme in MEAN

I am new in MEAN and going to create new website using MEAN.
I have created the package in MEAN using the command mean package <package_name>
I have also override the default templates using the app.set('views', __dirname + '/server/views'); command in the app.js of my custom package, but the MEAN is still rendering my angular views within the MEAN's default layout.
The structure of my MEAN package folder is
packages
--core
----admin
----articles
----circles
----swagger
----system
----users
--custom
----<my_package>
------public
--------assets
--------controllers
--------directives
--------routes
--------services
--------views
------server
--------config
--------controllers
--------models
--------routes
--------views
------.bowerrc
------app.js
------bower.json
------package.json
----i18n
----theme
How can I render my own theme
To change the layout view to a different one than the default view
In the routes folder under server parent folder, look for the file that has the function mapped to the route '/'.
Now look for that function in the controllers folder. Change the name of the view to render like this:
exports.index = function(req, res) {
res.render('differentviewfile', {
user: req.user || null,
request: req
});
};
To change the look and feel of your site
You can take advantage of numerous Bootstrap themes available out there. A lot of them are free. To use them, all you have to do is change the reference to the css file (you will find it in the server side view base layout page).
Change it from the default bootstrap file to a different one, and your whole app changes. For e.g. take a look at the 16 themes available at https://bootswatch.com You can reference the CDN link to any of the themes they have directly, or you can download the css file for it and add it to your own project.
If you want to add your own styles, you can of course create your own css file and add appropriate css styles.
Did you injected a dependency to system package in your app.js file?
var MyCustomModule = new Module('mycustommodule');
/*
* All MEAN packages require registration
* Dependency injection is used to define required modules
*/
MyCustomModule.register(function(system, app, auth, database) {
You need to do that in order to wait until the system package is loaded. Then the line:
app.set('views', __dirname + '/server/views');
will override the views config set in the system package :D

Resources