Trouble setting up sample table. "Could not find matching row model for rowModelType clientSide" - ag-grid-angular

I've been going through the "Getting Started" tutorial for the ag-grid on the fresh project. Completed all the steps but got an error saying
ag-Grid: could not find matching row model for rowModelType clientSide
ag-Grid: Row Model "Client Side" not found. Please ensure the ClientSideRowModelModule is loaded using: import '#ag-grid-community/client-side-row-model';
Compared all my code with examples provided in the tutorial and some plunker examples, and didn't notice any differences. Tried importing ClientSideRowModelModule to the app.module but interfaces did not match with what angular requested, so it didn't work. I'm out of ideas and failed to find any info on how to fix it.
app.module.ts:
... imports: [
BrowserModule,
AppRoutingModule,
AgGridModule.withComponents([])
],...
app.cpmponent.html:
<ag-grid-angular
style="width: 500px; height: 500px;"
class="ag-theme-balham"
[rowData]="rowData"
[columnDefs]="columnDefs"
>
</ag-grid-angular>
app.component.ts:
...columnDefs = [
{headerName: 'Make', field: 'make' },
{headerName: 'Model', field: 'model' },
{headerName: 'Price', field: 'price'}
];
rowData = [
{ make: 'Toyota', model: 'Celica', price: 35000 },
{ make: 'Ford', model: 'Mondeo', price: 32000 },
{ make: 'Porsche', model: 'Boxter', price: 72000 }
];...
I'm using Angular: 8.2.10, Angular CLI: 8.2.2, npm: 6.9.0

In your app.component.ts, you first need to import the ClientSideRowModelModule
import { ClientSideRowModelModule } from '#ag-grid-community/client-side-row-model';
Then inside the AppComponent class, you need to create a module array variable like this:
modules: Module[] = [ClientSideRowModelModule];
Finally, in your app.component.html, you need to bind it to the ag-grid-angular component
<ag-grid-angular
style="width: 500px; height: 500px;"
class="ag-theme-balham"
[rowData]="rowData"
[columnDefs]="columnDefs"
[modules]="modules"
>
</ag-grid-angular>
For further resource look at AgGrid's documentation, it is step 3 on installing AgGrid Modules.

I have been using the community version with no issues. I just downloaded a trial of enterprise and everything changed. When I ran into this issue, I learned that [modules]="modules" is required on the grid. That requires these two lines to be included on the component:
import { AllModules } from '#ag-grid-enterprise/all-modules';
modules: Module[] = AllModules;
I've never had to do this before in community version, but it quickly corrected the issue.
The answer that was accepted above is stating what needs to happen when your application is integrating only individual modules. Per the documentation: "If you choose to select individual modules then at a minimum the a Row Model need to be specified. After that all other modules are optional depending on your requirements".

To solve this problem, I had to first import ModuleRegistry and AllCommunityModules in maint.ts and add ModuleRegistry.registerModules(AllCommunityModules); below just before platformBrowserDynamic().bootstrapModule(AppModule) like:
import { ModuleRegistry, AllCommunityModules } from '#ag-grid-community/all-modules';
ModuleRegistry.registerModules(AllCommunityModules);
platformBrowserDynamic().bootstrapModule(AppModule)
.catch(err => console.error(err));
Lastly, in the component (e.g. users.component.ts) I used it by importing the AllCommunityModules and declaring the variable like:
import { AllCommunityModules } from '#ag-grid-community/all-modules';
public modules: Module[] = AllCommunityModules;
I got the idea from this answer here

It looks like you have installed AG Grid via its modules but then the code you are following assumes the use of the packaged versions.
As of v27 the all-modules packages are no longer recommended instead you should just use the following packages to have access to all the grid features.
"ag-grid-community": "^27.0.0",
"ag-grid-enterprise": "^27.0.0"
You only need to worry about the scoped packages if you are trying to reduce your bundle size. In that case, you should include the specific feature modules that you require.
From the docs
It is important that you do not mix packages and modules in the same
application as this will result in AG Grid being included twice and
doubling your bundle size! All modules are scoped by either
#ag-grid-community/* or #ag-grid-enterprise/* and should not be mixed
with the standalone packages of ag-grid-community and
ag-grid-enterprise.
Modules
Packages
#ag-grid-community/xxxxx
ag-grid-community
#ag-grid-enterprise/xxxxx
ag-grid-enterprise
I have written about this more in this blog post.

Related

Install Lottie Player to Angular

I'm currently trying to implement Lottie to my Angular web-app.
Somehow I couldn't manage to do so yet. I tried to follow the instructions from github, but that lead to multiple errors, as f.e.:
lottie-player is not a known ng module.
Furthermore, I tried to install ng-lottie for Angular - since the original wasn't working - but this one didn't provide any option to jump to a frame or loop only to a certain frame.
Does anyone know an alternative or a way to get lottie player working?
You can add lottie-player as a custom element schema
npm install --save #lottiefiles/lottie-player
angular.json
"scripts": [
"./node_modules/#lottiefiles/lottie-player/dist/lottie-player.js"
]
custom.module.ts
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '#angular/core';
#NgModule({
schemas: [ CUSTOM_ELEMENTS_SCHEMA ]
})
export class CustomModule { }
custom.component.html
<lottie-player src="https://assets4.lottiefiles.com/datafiles/zc3XRzudyWE36ZBJr7PIkkqq0PFIrIBgp4ojqShI/newAnimation.json" background="transparent" speed="1" loop autoplay >
</lottie-player>
Hope this helps! and if you managed to implements it with a different approach you can help by sharing it
theres a much simpler approach, install required packages as below
npm i ngx-lottie & lottie-web
in your app.module.ts, add
import { LottieModule } from 'ngx-lottie'; // add this line
export function playerFactory() { // add this line
return import('lottie-web'); // add this line
} // add this line
#NgModule({
declarations: ['your component 1', 'your component 2'...],
imports: [
LottieModule.forRoot({ player: playerFactory, useCache: true }) // add this line
]})
stop your angular server 4200 and start again using ng serve
define options in your component.ts file as
options: AnimationOptions = {
path: 'add animation json file link', // download the JSON version of animation in your project directory and add the path to it like ./assets/animations/example.json
};
then in your component.ts file
import the animation options module at the top of your component as
import { AnimationOptions } from 'ngx-lottie';
then in your component.html
<ng-lottie height="auto" [options]="options"></ng-lottie>
for more information on other attributes of ng-lottie tag visit
https://www.npmjs.com/package/ngx-lottie

How to read appsettings file in app.module in Angular 5?

Hi I am developing web application in Angular 5. I am trying to read appsettings.json and use the value in app.module.ts. In app.module.ts inside imports I have following line of code.
AppInsightsModule.forRoot('dfd77fnd-3ba9-43e6-a90f-3e762444938b')
In the above code value is hard coded. I have below tag in appsettings.json.
"ApplicationInsights": {
"InstrumentationKey": "dfd77fnd-3ba9-43e6-a90f-3e762444938b"
}
I want to read from appsettings.json. Below the app.module.ts I can read it. I have created service and inject it. App.module.ts the root file in Angular. Here how can i take the value from appsettings.json? Can someone help me to identify the solution for this? Any help would be appreciated. Thank you.
For loading the configuration data before application load you can use angular provided APP_INITIALIZER.
Details at :- https://devblog.dymel.pl/2017/10/17/angular-preload/
https://www.intertech.com/Blog/angular-4-tutorial-run-code-during-app-initialization/
providers: [
ConfigProvider,
{ provide: APP_INITIALIZER, useFactory: configProviderFactory, deps: [ConfigProvider], multi: true }
],
bootstrap: [AppComponent]

Quasar QSpinner module not found

Im getting the following error:
ERROR Failed to compile with 1 errors
This relative module was not found:
* ./QSpinner in ./node_modules/quasar-framework/src/components/spinner/index.js
Ive tried reinstalling quasar-cli and updating npm
im working with quasar-framework 0.15.8
and quasar-cli 0.15.12
Make sure you include QSpinner component.
Open quasar.conf.js file and look for framework components and add it there.
framework: {
components: [
'QSpinner',
'QLayout',
'QLayoutHeader',
'QLayoutDrawer',
'QPageContainer',
'QPage',
'QToolbar',
'QToolbarTitle',
'QBtn',
'QIcon',
'QList',
'QListHeader',
'QItem',
'QItemMain',
'QItemSide'
],
directives: [
'Ripple',
'TouchPan'
],
// Quasar plugins
plugins: [
'Notify'
]
},
If you already did so, try deleting node_modules and re-run 'npm install'
All of the quasar modules that you use in your project will be enabled if you set the all quasar.conf setting to "auto."
all to 'auto'
framework: {
iconSet: 'material-icons', // Quasar icon set
lang: 'en-us', // Quasar language pack
// Possible values for "all":
// * 'auto' - Auto-import needed Quasar components & directives
// (slightly higher compile time; next to minimum bundle size; most convenient)
// * false - Manually specify what to import
// (fastest compile time; minimum bundle size; most tedious)
// * true - Import everything from Quasar
// (not treeshaking Quasar; biggest bundle size; convenient)
all: 'auto',
components: [],
directives: [
'GoBack'
],
// Quasar plugins
plugins: [
'Loading',
'LocalStorage',
'SessionStorage',
'Notify'
]
},
So when you set property 'all' to 'auto', that means Auto-import needed Quasar components & directives
Include QSpinner component in quasar.conf.js file and look for framework components and in root directory there is a .quasar folder, inside it there are file import-quasar.js and quasar.js.
Vue.use(Quasar, {components: {QSpinner,QPagination,QChatMessage,QScrollArea,...
also import component at the beginning

Angular 4 dynamic component loading using a json schema

I am in process on creating a small poc to try whether is it possible to load components according to a given json data structure. json will provide and array of component selectors. I tried a small example according to the reference materials i found via online. I used the "componentFactoryResolver" which is recommended way by Angular
I basically create couple of components and registered it with the entrycomponent decorator as follow in my module
entryComponents: [PersonalDetailsComponent, ContactDetailsComponent],
and in my app component i use the following code
#ViewChild('dynamicInsert', { read: ViewContainerRef }) dynamicInsert: ViewContainerRef;
constructor(private componentFactoryResolver: ComponentFactoryResolver) {
}
ngAfterViewInit() {
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(PersonalDetailsComponent );
const componentFactory2 = this.componentFactoryResolver.resolveComponentFactory(ContactDetailsComponent);
this.dynamicInsert.clear();
this.dynamicInsert.createComponent(componentFactory);
this.dynamicInsert.createComponent(componentFactory2);
}
and as you see i have to create component for each and every component i use. but having this an inside a loop might not be the best way to do it. i would much appreciate if any one could give me some heads up to do it in a proper way.
my actual json would look like something like this
{
"step":"1",
"viewed":false,
"stepDependant":{
"parentComponent":null,
"childComponent":null,
"varMap":null
},
"widgets":[
{
"Component":"shipper",
"inputs":[
{
"ServiceLine":"Export"
}
],
"outputs":[
],
"name":"Shipper Details"
},
{
"Component":"shipper",
"inputs":[
{
"ServiceLine":"Export"
}
],
"outputs":[
],
"name":"Consignee Details"
},
{
"Component":"status-of-shipment",
"inputs":[
],
"outputs":[
],
"name":"Status of Shipment"
}
]
}
much appreciate your inputs
As you have already found the componentFactoryResolver is the correct way to create components dynamically from code.
With this approach what I would do in your case is create a map or service that maps the component selectors to component types. This way you can then quickly lookup the type when you are creating the dynamic components from the JSON data. From the types you then resolve the factory and then add the components like in your sample.
If you have a predefined set of components that are known another alternative would be to define them all as <ng-template> in the parent component like this:
<ng-template #shipper><shipper ></shipper></ng-template>
<ng-template #statusOfShippment><status-of-shipment ></status-of-shipment></ng-template>
Then you can get the templates in the component by using the #ViewChild decorator.
#ViewChild('shipper')
shipperTemplate: TemplateRef<any>;
#ViewChild('statusOfShippment')
statusOfShippmentTemplate: TemplateRef<any>;
And then you can create the components in a simmilar fashion than with the factory.
this.dynamicInsert.createEmbeddedView(shipper);
this.dynamicInsert.createEmbeddedView(statusOfShippment);
What is good about this approach is that you can still have classic template binding and send a different context object to every template.
<ng-template #shipper><shipper [ServiceLine]="ServiceLine"></shipper></ng-template>
this.dynamicInsert.createEmbeddedView(shipper, {ServiceLine:"Export"});
This way you could directly send an object created from your JSON and configure the component bindings. If you use the component factory you need to set everything from code manually.

How to bootstrap a JSON configuration file for an Angular 2 module without using a http.get approach

I have one json file at root:
config.json
{ "base_url": "http://localhost:3000" }
and in my service class, I want to use it in this way:
private productsUrl = config.base_url + 'products';
I've found a ton of posts with either solutions that require a http.get request to load that one file to get that one variable or outdated solutions for angular.js (angular 1)
I cant believe there isnt an easier way to include this file that we already have in place without having to make an additional request to the server.
In my opinion, I would have expected that at least the bootstrapping function would be able to provide this kind of functionality, something like:
platformBrowserDynamic().bootstrapModule(AppModule, { config: config.json });
btw, this works, but its not the ideal solution:
export class Config {
static base_url: string = "http://localhost:3004/";
}
and the use it where you need it:
private productsUrl = Config.base_url + 'products';
Its not ideal, because I will have to create the class (or replace properties) in a build script. (exactly what I was thinking to do with the config.json file).
I still prefer the config.json file approach, since it would not be intrusive with the TypeScript compiler. Any ideas how to do are welcome and really appreciated!
This link explains how to use System.js to load json files in an angular app.
Special thanks to #eotoole that pointed me in the right direction.
If the link above is not clear enough, just add a map into the System.js conf. like this:
map: { 'plugin-json': 'https://unpkg.com/systemjs-plugin-json' }*
*(using external package)
or
map: { 'plugin-json': 'plugin-json/json.js' }**
**if you download the plugin from:
official system.js plugin
now I can use:
const config = require('./config.json');
anywere in my app.
and since it is official from the "systemjs" - guys, I feel comfortable using it to load app settings like base_url or other endpoints.
Now I need to figure out how to encapsulate this logic for testing purposes. Maybe requiring the file in its own class and replacing the values for the specific test case.
Are you using webpack? If you are, and you can just do
const config = require('./config.json');
#Injectable()
export class MyService {
private config:any = config;
....
}
in your webpack config you will need the json-loader
...
module: {
...
loaders: [
...
{
test: /\.json$/,
loaders: ["json-loader"]
},
...
]
}
...