Angular SSR: not rendering pure html page - angularjs

We are working on a angularJs project where our homepage contains code in which we call some APIs and fill the data accordingly. We need server side rendering and so we followed this tutorial . We ran npm run dev:ssr Everything is working fine however we are not getting fully generated pure html/css page. i can see page hasn't been rendered server side yet. It is still getting rendered in browser side. I don't know what i am doing wrong here. Any help will be appreciated.
Nodejs version : 14.17.2
OS : ubuntu 20.
Here is my package.json file :-
{
"name": "piping-mart-client",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"watch": "ng build --watch --configuration development",
"test": "ng test",
"dev:ssr": "ng run pipingMartClient:serve-ssr",
"serve:ssr": "node dist/pipingMartClient/server/main.js",
"build:ssr": "ng build && ng run pipingMartClient:server",
"prerender": "ng run pipingMartClient:prerender"
},
"private": true,
"dependencies": {
"#angular/animations": "~13.1.0",
"#angular/common": "~13.1.0",
"#angular/compiler": "~13.1.0",
"#angular/core": "~13.1.0",
"#angular/forms": "~13.1.0",
"#angular/localize": "~13.1.0",
"#angular/platform-browser": "~13.1.0",
"#angular/platform-browser-dynamic": "~13.1.0",
"#angular/platform-server": "~13.1.0",
"#angular/router": "~13.1.0",
"#ng-bootstrap/ng-bootstrap": "^12.0.0",
"#ng-select/ng-select": "^8.1.1",
"#nguniversal/express-engine": "^13.0.2",
"#popperjs/core": "^2.10.2",
"angular-material": "^1.2.5",
"angular-ng-autocomplete": "^2.0.8",
"angular-responsive-carousel": "^2.1.2",
"bootstrap": "^5.1.3",
"countrycitystatejson": "^20.8.14",
"ejs": "^3.1.6",
"express": "^4.15.2",
"font-awesome": "^4.7.0",
"intl-tel-input": "^17.0.16",
"jquery": "^3.6.0",
"localstorage-polyfill": "^1.0.1",
"ng2-tel-input": "^2.3.0",
"ngx-owl-carousel-o": "^7.0.2",
"ngx-select-dropdown": "^2.1.0",
"ngx-slick-carousel": "^0.6.0",
"path": "^0.12.7",
"rxjs": "~7.4.0",
"sessionstorage": "^0.1.0",
"slick-carousel": "^1.8.1",
"sweetalert2": "^11.4.9",
"tslib": "^2.3.0",
"zone.js": "~0.11.4"
},
"devDependencies": {
"#angular-devkit/build-angular": "^13.2.6",
"#angular/cli": "~13.1.2",
"#angular/compiler-cli": "~13.1.0",
"#nguniversal/builders": "^13.0.2",
"#types/express": "^4.17.0",
"#types/jasmine": "~3.10.0",
"#types/node": "^12.11.1",
"jasmine-core": "~3.10.0",
"karma": "~6.3.0",
"karma-chrome-launcher": "~3.1.0",
"karma-coverage": "~2.1.0",
"karma-jasmine": "~4.0.0",
"karma-jasmine-html-reporter": "~1.7.0",
"typescript": "~4.5.2"
}
}
My productcomponent.html page (this is the page which we expect to be rendered. This is the first page which get loaded whenever app is loaded).
<div id="content">
<div class="container">
<div class="row">
<div class="col-md-3 col-sm-6 col-sm-12">
<div class="pro-circle p-4">
<img src="{{this.product?.logo || 'https://www.example.com/images/logo.png'}}" class="img-responsive lazyload" alt="Pipes" title="Pipes" />
<h1 class="tab-title">{{this.product.name}}</h1>
</div>
</div>
<div class="col-md-9 col-sm-6 col-sm-12" id="description">
<div id="ProdDesc" class="text show-more-height" [innerHTML]="this.product['description']" >
</div>
<div class="show-more"><button class="btn more">Show More</button></div>
<div class="clearfix"></div>
<div class="container mt-5">
<div class="slide-box mt-5" *ngFor="let slide of material; let i = index;">
<div class="recent-projects">
<a (click)="goToSupplierOfMaterial(slide)" >
<h4 class="title">
<span >{{slide.name}} </span></h4></a>
<div class="projects-carousel touch-carousel">
<owl-carousel-o [options]="customOptions">
<ng-container *ngFor="let gradeList of slide.gradeDetail">
<ng-template carouselSlide [id]="gradeList.gradeId">
<img [src]="gradeList.logo" [alt]="gradeList.alt" [title]="gradeList.name" style="height: 20vh;">
<div class="portfolio-details text-center">
<a class="text-underline cursor-pointer" >
<h4 (click)="goToSupplier(gradeList)">{{gradeList.name}}</h4>
</a>
</div>
</ng-template>
</ng-container>
</owl-carousel-o>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
My product.component.ts page :-
import { HttpClient } from '#angular/common/http';
import { Component, OnInit , PLATFORM_ID , Inject} from '#angular/core';
import { ActivatedRoute , Router} from '#angular/router';
import { OwlOptions } from 'ngx-owl-carousel-o';
import { CookieService } from 'src/app/shared/service/cookie.service';
import { DataService } from 'src/app/shared/service/DataService';
import * as $ from "jquery";
import { isPlatformBrowser , isPlatformServer} from '#angular/common'
#Component({
selector: 'app-product',
templateUrl: './product.component.html',
styleUrls: ['./product.component.scss']
})
export class ProductComponent implements OnInit {
htmlPage : any;
name : any;
selectedProduct : any [];
arrayOfValues: Array<string>;
productCategory: any;
product: any;
material: any;
materialArray = [];
customOptions: OwlOptions = {
loop: false,
mouseDrag: true,
autoplay: true,
touchDrag: false,
pullDrag: false,
dots: false,
margin: 10,
navSpeed: 700,
navText: ['<i class="fa-solid fa-chevron-left"></i>', '<i class="fa fa-angle-right" aria-hidden="true"></i>'],
responsive: {
0: {
items: 1
},
400: {
items: 4
},
740: {
items: 4
},
940: {
items: 4
}
},
nav: true
}
description: string;
constructor(private activatedRoute : ActivatedRoute ,
private router : Router ,
private _dataService : DataService,
private http : HttpClient ,
private cookieService: CookieService ,
#Inject(PLATFORM_ID) private _platformId: Object) { }
ngOnInit(){
if (isPlatformBrowser(this._platformId)) {
this.activatedRoute.params.subscribe(params => {
this.name = params['name'];
});
this.product = JSON.parse(localStorage.getItem("selectedProduct"));
this.fetchMaterial(this.product['productId'])
}
$(".show-more").click(function () {
if($(".text").hasClass("show-more-height")) {
$(this).text("Show Less...");
} else {
$(this).text("Show More...");
}
$(".text").toggleClass("show-more-height");
});
}
public fetchMaterial(productId){
this.http.post('http://pipe.example.com/product/materials',{"productId" : productId , "includeGrades": true
}).subscribe(
(res : any) => {
this.material = res.data;
},
error => {
console.log(JSON.stringify(error.json()));
}
)
}
public fetchProduct() {
this.http.post('http://pipe.example.com/product/products',{"name" : this.name }).subscribe(
(res : any) => {
//this.productCategory = res.data;
//console.log(res.data);
this.selectedProduct = res.data;
},
error => {
console.log(JSON.stringify(error.json()));
}
)
}
public goToSupplier(grade) {
console.log(grade);
this.router.navigate(['/product/detail/'+ grade.name]);
localStorage.setItem("selectedGrade", JSON.stringify(grade));
}
public goToSupplierOfMaterial(material) {
console.log(material);
this.router.navigate(['/material/'+ material.name]);
localStorage.setItem("selectedMaterial", JSON.stringify(material));
}
}
my server.ts file (got generated after running ng add #nguniversal/express-engine)
import 'zone.js/dist/zone-node';
import { ngExpressEngine } from '#nguniversal/express-engine';
import * as express from 'express';
import { join } from 'path';
import { AppServerModule } from './src/main.server';
import { APP_BASE_HREF } from '#angular/common';
import { existsSync } from 'fs';
// The Express app is exported so that it can be used by serverless Functions.
export function app(): express.Express {
const server = express();
const distFolder = join(process.cwd(), 'dist/pipingMartClient/browser');
const indexHtml = existsSync(join(distFolder, 'index.original.html')) ? 'index.original.html' : 'index';
// Our Universal express-engine (found # https://github.com/angular/universal/tree/master/modules/express-engine)
server.engine('html', ngExpressEngine({
bootstrap: AppServerModule,
}));
server.set('view engine', 'html');
server.set('views', distFolder);
// Example Express Rest API endpoints
// server.get('/api/**', (req, res) => { });
// Serve static files from /browser
server.get('*.*', express.static(distFolder, {
maxAge: '1y'
}));
// All regular routes use the Universal engine
server.get('*', (req, res) => {
res.render(indexHtml, { req, providers: [{ provide: APP_BASE_HREF, useValue: req.baseUrl }] });
});
return server;
}
function run(): void {
const port = process.env['PORT'] || 4000;
// Start up the Node server
const server = app();
server.listen(port, () => {
console.log(`Node Express server listening on http://localhost:${port}`);
});
}
// Webpack will replace 'require' with '__webpack_require__'
// '__non_webpack_require__' is a proxy to Node 'require'
// The below code is to ensure that the server is run only when not requiring the bundle.
declare const __non_webpack_require__: NodeRequire;
const mainModule = __non_webpack_require__.main;
const moduleFilename = mainModule && mainModule.filename || '';
if (moduleFilename === __filename || moduleFilename.includes('iisnode')) {
run();
}
export * from './src/main.server';

Related

Are dynamic and external React components possible in runtime?

We're developing a dashboard React-application in which other (trusted) developers can create their own React-widgets in separate environments. The goal would be a situation where new widgets wouldn't require updation to the dashboard-application and instead, these external React-components could be loaded at runtime.
So developer A would have his own project, where he would bundle a React-component into a js-file, which would be forwarded to a hosting site, S3 for example where the dashboard application could read them via a string, at runtime.
For example a weather-widget:
import React, {useState} from "react";
function Weather() {
const [city, setCity] = useState("city");
const weatherUri = `https://wttr.in/${city}_tqp0.png`;
return (
<div>
<input type="text" value={city} onChange={(e) => setCity(e.target.value)}/>
<div>
<img src={weatherUri} alt={city}/>
</div>
</div>
);
}
export default Weather;
This could be then imported to the dashboard-application. I've understood that React's dynamic code-splitting with dynamic url would work here. Either via a situation where widget would have its own React-library, or it'd get it from the dashboard-application. We've, in fact, made this to work, but as soon as we add a state to the component, it breaks:
Uncaught TypeError: Cannot read properties of null (reading 'useState')
at Object.useState (react.development.js:1612:23)
at Weather (weather_widget.js:36:33)
We've configured the widget-component's configuration as follows (React-library will be imported from the dashboard-application):
// ====== vite.config.js ========== (widget)
export default defineConfig({
plugins: [react()],
define: {
'process.env': {}
},
build: {
lib: {
entry: 'src/lib/Weather.tsx',
name: 'Weather',
fileName: 'weather',
formats: ['es']
},
rollupOptions: {
plugins: [
externalGlobals({
react: "React"
})
],
external: ['react'],
output: {
globals:{
react: 'React'
}
}
}
},
})
// ===== package.json ===== (widget)
{
"name": "weather",
"private": true,
"version": "0.0.0",
"type": "module",
"files": [
"dist"
],
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"preview": "vite preview"
},
"dependencies": {
"react": "18.2.0",
"react-dom": "18.2.0",
"rollup-plugin-external-globals": "^0.6.1"
},
"devDependencies": {
"#types/node": "18.7.23",
"#types/react": "18.0.21",
"#types/react-dom": "^18.0.6",
"#vitejs/plugin-react": "^1.0.7",
"path": "^0.12.7",
"typescript": "^4.6.4",
"vite": "^2.8.0"
}
}
This is how we've tried to import it to the dashboard-application:
export const WidgetCard = (widgetId: string) => {
const WidgetComponent = React.lazy(() =>
import(`/path/to/${widgetId}.js`));
return
<>
<Suspense fallback={<Loading/>}>
<WidgetComponent/>
</Suspense>
</>
)
});
For the final product, the logic would be as follows:
User will generate a JS-bundle of their React-component
User will call some sort of API, which will save bundle to a hosting site and also add the new widget to a database of some sort.

My Uppy suddenly gives me the error this.uppy.addFiles is not a function

I'm new to this and I get this error and can't figure out why please advice:
Looks like the Error is inside Uppy something.
I follow Uppy Tutorial docs like .use(Dashboard, {... and it was working but suddenly this error I try to back track but no luck
I add files from My Device and and then error happens no breakpoint are hit anywhere what I'm a missing
Here is my simple Uppy:
import React from "react";
import "#uppy/core/dist/style.css";
import "#uppy/status-bar/dist/style.css";
import "#uppy/drag-drop/dist/style.css";
import "#uppy/progress-bar/dist/style.css";
import "#uppy/dashboard/dist/style.css";
import "./styles.css";
const Uppy = require("#uppy/core");
// const Dashboard = require("#uppy/dashboard");
const GoogleDrive = require("#uppy/google-drive");
const Dropbox = require("#uppy/dropbox");
const Instagram = require("#uppy/instagram");
const Webcam = require("#uppy/webcam");
const Tus = require("#uppy/tus");
const {
Dashboard,
DashboardModal,
DragDrop,
ProgressBar,
} = require("#uppy/react");
class DashboardUppy extends React.Component {
constructor(props) {
super(props);
this.form = React.createRef();
this.state = {
showInlineDashboard: false,
open: false,
};
this.uppy = new Uppy({
id: "uppy1",
autoProceed: false,
debug: true,
allowMultipleUploads: true,
showSelectedFiles: true,
restrictions: {
maxFileSize: 1000000,
maxNumberOfFiles: 100,
minNumberOfFiles: 1,
allowedFileTypes: ['image/*', 'video/*'],
},
onBeforeFileAdded: (currentFile, files) => {
console.log(files);
const modifiedFile = Object.assign({}, currentFile, {
name: currentFile + Date.now(),
});
if (!currentFile.type) {
// log to console
this.uppy.log(`Skipping file because it has no type`);
// show error message to the user
this.uppy.info(`Skipping file because it has no type`, "error", 500);
return false;
}
return modifiedFile;
},
})
.use(Tus, { endpoint: "https://master.tus.io/files/" })
.use(GoogleDrive, { companionUrl: "https://companion.uppy.io" })
.use(Dropbox, {
companionUrl: "https://companion.uppy.io",
})
.use(Instagram, {
companionUrl: "https://companion.uppy.io",
})
.use(Webcam, {
onBeforeSnapshot: () => Promise.resolve(),
countdown: false,
modes: ["video-audio", "video-only", "audio-only", "picture"],
mirror: true,
facingMode: "user",
locale: {
strings: {
// Shown before a picture is taken when the `countdown` option is set.
smile: "Smile!",
// Used as the label for the button that takes a picture.
// This is not visibly rendered but is picked up by screen readers.
takePicture: "Take a picture",
// Used as the label for the button that starts a video recording.
// This is not visibly rendered but is picked up by screen readers.
startRecording: "Begin video recording",
// Used as the label for the button that stops a video recording.
// This is not visibly rendered but is picked up by screen readers.
stopRecording: "Stop video recording",
// Title on the “allow access” screen
allowAccessTitle: "Please allow access to your camera",
// Description on the “allow access” screen
allowAccessDescription:
"In order to take pictures or record video with your camera, please allow camera access for this site.",
},
},
})
.on("file-added", (file) => {
const { setFiles } = props;
setFiles(file);
})
}
componentWillUnmount() {
this.uppy.close();
}
render() {
this.uppy.on("complete", (result) => {
console.log(
"Upload complete! We’ve uploaded these files:",
result.successful
);
});
return (
<div>
<div>
<Dashboard
uppy={this.uppy}
plugins={["GoogleDrive", "Webcam", "Dropbox", "Instagram"]}
metaFields={[
{ id: "name", name: "Name", placeholder: "File name" },
]}
open={this.state.open}
target={document.body}
onRequestClose={() => this.setState({ open: false })}
/>
</div>
</div>
);
}
}
export default DashboardUppy;
And I use it like this nothing special:
import React, { useState } from "react";
import FileList from "./FileList";
import FileForm from "./FileForm";
import DashboardUppy from "./DashboardUppy";
import { Container, Grid } from "#material-ui/core";
const CreateContent = () => {
const [file, setItems] = useState();
const [show, showDashboardUppy] = useState(true);
return (
<Container maxWidth="lg">
{show ? (
<DashboardUppy showDashboardUppy={showDashboardUppy}/>
) : (
<Grid container spacing={3}>
<Grid item lg={4} md={6} xs={12}>
<FileList setItems={setItems} />
</Grid>
<Grid item lg={8} md={6} xs={12}>
<FileForm file={file} />
</Grid>
</Grid>
)}
</Container>
);
};
export default CreateContent;
Here is package.json
{
"name": "react-firestore-crud",
"version": "0.1.0",
"private": true,
"dependencies": {
"#uppy/core": "1.0.2",
"#uppy/dropbox": "latest",
"#uppy/form": "^1.3.23",
"#uppy/google-drive": "1.0.2",
"#uppy/instagram": "1.0.2",
"#uppy/react": "^1.0.2",
"#uppy/status-bar": "latest",
"#uppy/tus": "1.0.2",
"#uppy/webcam": "latest",
"#uppy/xhr-upload": "^1.6.8",
"#material-ui/core": "^4.11.2",
"#material-ui/icons": "^4.11.2",
"#material-ui/lab": "^4.0.0-alpha.57",
"#material-ui/styles": "^4.11.2",
"#testing-library/jest-dom": "^4.2.4",
"#testing-library/react": "^9.3.2",
"#testing-library/user-event": "^7.1.2",
"bootstrap": "^4.5.2",
"clsx": "^1.1.1",
"firebase": "^7.23.0",
"moment": "^2.29.1",
"prop-types": "^15.7.2",
"react": "^16.8.4",
"react-dom": "^16.8.4",
"react-perfect-scrollbar": "^1.5.8",
"react-router-dom": "^5.2.0",
"react-scripts": "^3.4.0",
"uuid": "^8.3.2"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
I hade the wrong Uppy version in package.json hmmm

gatsby-source-graphql only absolute urls are supported

I'm integrating graphQL into my gatsby site. I am getting an error that says "only absolute urls are supported" and then points to some code in the node-fetch library. There isn't an obvious path to how I'm getting that code to execute though, so I'm not sure what the source of my issue is. I have done several days worth of searching, and while I have found several threads about this error, it's never been in the context of gatsby-source-graphql. Any help would be appreciated.
package.json
{
.
.
.
"dependencies": {
"ajv": "^6.9.2",
"core-js": "^2.6.5",
"fullcalendar": "^3.9.0",
"fullcalendar-reactwrapper": "^1.0.7",
"gatsby": "^2.12.0",
"gatsby-cli": "^2.7.20",
"gatsby-plugin-manifest": "^2.0.2",
"gatsby-plugin-netlify-cms": "^4.0.1",
"gatsby-plugin-offline": "^2.0.5",
"gatsby-plugin-react-helmet": "^3.0.0",
"gatsby-plugin-sass": "^2.0.1",
"gatsby-source-filesystem": "^2.1.6",
"gatsby-source-graphql": "^2.1.3",
"gatsby-transformer-remark": "^2.6.9",
"graphql": "^14.1.1",
"jquery": "^3.3.1",
"moment": "^2.22.2",
"netlify-cms-app": "^2.9.1",
"node-sass": "^4.9.3",
"react": "^16.5.1",
"react-calendar": "^2.17.5",
"react-dom": "^16.6.3",
"react-helmet": "^5.2.0",
"react-native-calendars": "^1.21.0"
},
.
.
.
"devDependencies": {
"#material-ui/core": "^3.9.2",
"#material-ui/icons": "^3.0.2",
"material-icons-react": "^1.0.4",
"prettier": "^1.14.2",
"react-tooltip": "^3.9.2",
"surge": "^0.20.1"
},
.
.
.
}
UpcomingScheduleChanges.js
import React from 'react';
import { StaticQuery, graphql } from 'gatsby';
import Cancellations from './Cancellations';
class UpcomingScheduleChanges extends React.Component {
render() {
console.log(this.props.cancellations)
return (
<div className="col-6">
<header className="major">
<h2>Upcoming Schedule Changes</h2>
</header>
{this.props.cancellations ? (
<Cancellations cancellations={this.props.cancellations}></Cancellations>
) : (
<p>There are no upcomimng schedule changes!</p>
)}
</div>
)
}
}
export default () => (
<StaticQuery
query={graphql`
query ScheduleChanges {
allMarkdownRemark {
edges {
node {
frontmatter {
cancellation {
date(formatString: "MMMM DD")
day
location
type
}
}
}
}
}
}
`}
render={(data) => <UpcomingScheduleChanges cancellations={data.allMarkdownRemark.edges[0].node.frontmatter.cancellation} />}
/>
);
index.js
import React from "react";
import Helmet from "react-helmet";
import Layout from "../components/layout";
import ReactTooltip from "react-tooltip";
import ContactForm from "../components/ContactForm";
import Schedule from '../components/Schedule';
import Welcome from "../components/Welcome";
import Administrators from "../components/Administrators";
import MailingList from "../components/MailingList";
class Homepage extends React.Component {
handleClick(url) {
window.open(url, "_blank");
}
render() {
const siteTitle = "...";
return (
<Layout>
<Helmet title={siteTitle}>
<script src="https://identity.netlify.com/v1/netlify-identity-widget.js"></script>
</Helmet>
<Welcome></Welcome>
<Schedule></Schedule>
<Administrators></Administrators>
<MailingList></MailingList>
<ContactForm></ContactForm>
<ReactTooltip />
<script>
{`if (window.netlifyIdentity) {
window.netlifyIdentity.on("init", user => {
if (!user) {
window.netlifyIdentity.on("login", () => {
document.location.href = "/admin/";
});
}
});
}`}
</script>
</Layout>
);
}
}
export default Homepage;
gatsby-config.js
module.exports = {
siteMetadata: {
title: "...",
author: "...",
description: "..."
},
plugins: [
'gatsby-plugin-react-helmet',
{
resolve: `gatsby-plugin-manifest`,
options: {
name: '...',
short_name: '...',
start_url: '/',
background_color: '#FFFFFF',
theme_color: '#FFFFFF',
display: 'minimal-ui',
icon: 'src/assets/images/banner_small.png', // This path is relative to the root of the site.
},
},
'gatsby-plugin-sass',
'gatsby-transformer-remark',
{
resolve: 'gatsby-source-filesystem',
options: {
path: `${__dirname}/static/content`,
name: 'content'
}
},
{
resolve: "gatsby-source-graphql",
options: {
typeName: "cancellations",
fieldName: "cancellations",
url: `${__dirname}/static/content/cancellations.md`
}
},
'gatsby-plugin-offline',
'gatsby-plugin-netlify-cms'
],
}
config.yml
backend:
name: git-gateway
branch: master #branch to update (optional; defaults to master)
publish_mode: editorial_workflow #allows for a drafting, reviewing, and approving process for changes
media_folder: "src/assets/images/uploads"
public_folder: "/images"
#collections
collections:
- label: "Upcoming Schedule Changes"
name: "upcoming schedule changes"
files:
- label: "Cancellations"
name: "cancellations"
file: "static/content/cancellations.md"
fields:
- label: "Cancellations"
name: "cancellations"
create: true
widget: "list"
fields:
- {label: "Date", name: "date", widget: "date"}
- {label: "Day", name: "day", widget: "select", options: ["Thursday", "Friday", "Sunday"]}
- {label: "Location", name: "location", widget: "select", options: ["Location1", "Location2", "Location3"]}
- {label: "Type", name: "type", widget: "select", options: ["Cancelled", "Delayed", "Relocated"]}

Reactjs returns error unexpected token with dropdown menu records

I know this question may have been asked but am just frustrated. Reactjs marks = at the line of code below as unexpected token error
handleChange1 = {(selectedOption) => {
All the required dependency has been installed.
below is the entire code
import React, { Component } from 'react';
import { render } from 'react-dom';
import { Link } from 'react-router-dom';
import { connect } from 'react-redux';
import Hello from './Hello';
import Select from 'react-select'
//import './style.css';
import 'react-select/dist/react-select.css';
class Plans extends Component {
constructor() {
super();
this.state = {
name: 'React',
selectedOption: {},
selectedOption2: {}
};
}
handleChange1 = {(selectedOption) => {
this.setState({selectedOption});
}
};
handleChange2 = (selectedOption) => {
this.setState({selectedOption2: selectedOption})
}
render() {
const options1 = [
{value: 'one', label: 'One'},
{value: 'two', label: 'Two'}
];
const options2 = [
{value: 'one-a', label: 'One A', link: 'one'},
{value: 'one-b', label: 'One B', link: 'one'},
{value: 'two-a', label: 'Two A', link: 'two'},
{value: 'two-b', label: 'Two B', link: 'two'}
];
const filteredOptions = options2.filter((o) => o.link === this.state.selectedOption.value)
return (
<div>
<p>Select one first</p>
<Select
name="form-field-name"
value={this.state.selectedOption.value}
onChange={this.handleChange1}
options={options1}
/>
<p>Then the other</p>
<Select
name="form-field-name"
value={this.state.selectedOption2.value}
onChange={this.handleChange2}
options={filteredOptions}
/>
</div>
);
}
}
//render(<Plans />, document.getElementById('app'));
function mapStateToProps(state) {
}
const connectedPlans = connect(mapStateToProps)(Plans);
export { connectedPlans as Plans };
Here is my package.json
{
"name": "example",
"version": "1.0.0",
"repository": {
"type": "git",
"url": ""
},
"license": "MIT",
"scripts": {
"start": "webpack-dev-server --open"
},
"dependencies": {
"history": "^4.6.3",
"node-sass": "^4.9.4",
"react": "^16.0.0",
"react-dom": "^16.0.0",
"react-redux": "^5.0.5",
"react-router-dom": "^4.1.2",
"react-select": "^2.1.1",
"react-toastify": "^4.4.0",
"redux": "^3.7.2",
"redux-logger": "^3.0.6",
"redux-thunk": "^2.2.0"
},
"devDependencies": {
"babel-core": "^6.21.0",
"babel-loader": "^7.1.2",
"babel-preset-es2015": "^6.18.0",
"babel-preset-react": "^6.16.0",
"babel-preset-stage-3": "^6.24.1",
"css-loader": "^1.0.1",
"html-webpack-plugin": "^2.26.0",
"path": "^0.12.7",
"sass-loader": "^7.1.0",
"style-loader": "^0.23.1",
"webpack": "^3.6.0",
"webpack-dev-server": "^2.8.2"
}
}
Updates
App.jsx
import React from 'react';
import { Router, Route } from 'react-router-dom';
import { connect } from 'react-redux';
import { history } from '../_helpers';
import { alertActions } from '../_actions';
import { PrivateRoute } from '../_components';
import { Plans } from '../Plans';
class App extends React.Component {
constructor(props) {
super(props);
const { dispatch } = this.props;
history.listen((location, action) => {
// clear alert on location change
dispatch(alertActions.clear());
});
}
render() {
const { alert } = this.props;
return (
<div className="jumbotron">
<div className="container">
<div className="col-sm-8 col-sm-offset-2">
{alert.message &&
<div className={`alert ${alert.type}`}>{alert.message}</div>
}
<Router history={history}>
<div>
<Route path="/plans" component={Plans} />
</div>
</Router>
</div>
</div>
</div>
);
}
}
function mapStateToProps(state) {
const { alert } = state;
return {
alert
};
}
const connectedApp = connect(mapStateToProps)(App);
export { connectedApp as App };
How I solve the problem. First I implemented the solution powered by Dacre in the comments above. I then discovered that react-select.css' files is not in the node_modules so I re-install it again so as to enable me to import it..
I added this line of code below
render(<Plans />, document.getElementById('app'));
and then remove the code below
function mapStateToProps(state) {
}
const connectedPlans = connect(mapStateToProps)(Plans);
export { connectedPlans as Plans };

Angular Hybrid Error: Trying to get the AngularJS injector before it being set

How to use AngularJS service in Angular 5 component?
I have AngularJS application and i am trying to make hybrid app but not able to use AngularJS service insight Angular component : getting error
ERROR Error: Trying to get the AngularJS injector before it being set.
my main.ts is
import { platformBrowserDynamic } from '#angular/platform-browser-dynamic';
import { AppModule } from './app.module';
platformBrowserDynamic().bootstrapModule(AppModule);
app.module :
import { BrowserModule } from '#angular/platform-browser';
import { NgModule, InjectionToken } from '#angular/core';
import { FormsModule } from '#angular/forms';
import { UpgradeModule, downgradeComponent } from '#angular/upgrade/static';
import { AppComponent } from './app.component';
import { SignInComponent } from "./modules/login/components/sign-in/sign-in.component";
import { authServiceProvider } from './shared/angularJS-upgraded-providers';
#NgModule({
declarations: [
AppComponent,
SignInComponent
],
imports: [
BrowserModule,
UpgradeModule,
FormsModule
],
entryComponents: [
SignInComponent
],
providers: [authServiceProvider],
bootstrap: [SignInComponent]
})
export class AppModule {
ngDoBootstrap() {}
}
angularJS-upgraded-providers.ts :
import { InjectionToken } from "#angular/core";
export const AuthService = new InjectionToken<any>('authService');
export function authServiceFactory(i: any) {
return i.get('authService');
}
export const authServiceProvider = {
provide: AuthService,
useFactory: authServiceFactory,
deps: ['$injector']
};
and sign-in.component.ts :
import { Component, Inject } from '#angular/core';
import {AuthService} from "../../../../shared/angularJS-upgraded-providers";
#Component({
selector: 'sign-in',
template: require('./sign-in.component.html')
})
export class SignInComponent {
constructor(
#Inject(AuthService) private authService: any) {
}
}
When I remove SignInComponent constructor part code compiles well but with #Inject(AuthService) private authService: any) { } part I am getting an error :
Trying to get the AngularJS injector before it being set.
Please give me some suggesting how can I implement angularJS service insight Angular component.
Thanks
P.S. my package.json :
{
"name": "test",
"version": "1.0.0",
"private": true,
"scripts": {
"start": "webpack-dev-server --port=4200 --open chrome"
},
"dependencies": {
"#angular/common": "^5.2.11",
"#angular/compiler": "^5.2.11",
"#angular/core": "^5.2.11",
"#angular/forms": "^5.2.11",
"#angular/http": "^5.2.11",
"#angular/platform-browser": "^5.2.11",
"#angular/platform-browser-dynamic": "^5.2.11",
"#angular/router": "^5.2.11",
"#angular/upgrade": "^5.2.11",
"core-js": "^2.5.7",
"reflect-metadata": "^0.1.12",
"rxjs": "^5.5.11",
"zone.js": "^0.8.26"
},
"devDependencies": {
"#types/jquery": "^3.3.6",
"#types/node": "^8.10.23",
"awesome-typescript-loader": "^5.2.0",
"css-loader": "^1.0.0",
"html-loader": "^0.5.5",
"html-webpack-plugin": "^3.2.0",
"raw-loader": "^0.5.1",
"style-loader": "^0.22.1",
"ts-loader": "3.2.0",
"typescript": "^2.9.2",
"webpack": "^4.16.5",
"webpack-cli": "^3.1.0",
"webpack-dev-server": "^3.1.5"
}
}
And AngularJS version : 1.6.8
This means you are pulling in an AngularJS dependency somewhere in your component tree. It may be in your immediate component or some dependency further down the line.
To debug:
Method 1
Add a debugger statement immediately before your bootstrap call:
it('should render the component', () => {
debugger;
bootstrap(Ng2AppComponent);
...
});
With your JS Console open, let the test run and pause at the debugger location.
Click the Stop/Pause icon (in the sidebar on the 'sources' tab) and checkmark "Pause on Exceptions". Unpause the debugger.
The debugger should stop within a call to injectorFactory. Use the stack explorer to find calls to resolveNgModuleDep. These will be recursive, so the top of the stack will be closer to a leaf node, while calls further down the stack will be closer to your component being tested. Look for lines like: tokenKey = "ServiceName". This is potentially your offending service.
Dive down the stack one more layer to find which component tried to inject that service.
Within your test, mock out a provider to handle that specific injection. Note that this code assumes only one problem injection. For multiple injector issues, you will need to special case these:
beforeEach(() => {
setupModule({
imports: [
...
],
providers: [
{
provide: '$injector',
useValue: {
get: () => {
return new MockService(); // enhance as needed
},
}
}
],
});
Method 2
Mock out a provider for the $injector call, and return an empty object.
beforeEach(() => {
setupModule({
imports: [
...
],
providers: [
{
provide: '$injector',
useValue: {
get: (serviceName?: string) => {
console.log('looking for serviceName:', serviceName);
return {}; // this will break things differently
},
}
}
],
});
Look at your console output to find the offending service / signature. This may or may not involve less work than than Method 1.

Resources