Showing posts with label Angular. Show all posts
Showing posts with label Angular. Show all posts

Thursday, 12 November 2020

Angular: Changing font-size using css variables is applying but not reflecting in browser for certain fields

I am using CSS variables for a feature where the user has an option to change the font-size to small, medium or large. So for most of the fields, it's working as expected. But for certain fields, the value is applied but not reflected

:host-context(.mediumFont) {
    --fontSize: 11px;
}
:host-context(.largeFont) {
    --fontSize: 12px;
}
:host-context(.smallFont) {
    --fontSize: 10px;
}

refClassArray: RefClassInterface[] = [
        { class: 'font-small', refClass: 'smallFont' },
        { class: 'font-medium', refClass: 'mediumFont' },
        { class: 'font-large', refClass: 'largeFont' },
    ];
defaultFontSize = 'mediumFont';

changeFontSize(selector: string) {
        this.defaultFontSize = selector;
        let docBody = document.body;
        console.log(document.getElementById(selector));
        docBody.classList.add(selector);
        this.refClassArray.forEach((refClass: RefClassInterface) => {
            if (selector !== refClass.refClass) {
                docBody.classList.remove(refClass.refClass);
                document.querySelector('#' + refClass.refClass).setAttribute('style', 'font-weight: normal;' + 'pointer-events: auto;');
            } else {
                document.querySelector('#' + refClass.refClass).setAttribute('style', 'font-weight:' + 'bold;' + 'pointer-events: none;');
            }
        });
        this.ieStyles.iEfont(selector);
    }

Above is the logic I am using.

enter image description here

enter image description here

The first pic is from the element which is working fine. When I hover over the --font-size, 11px is reflected. The second one is the one where it's not working as expected and when I hover over the --font-size nothing is appearing. And both these elements are inside <body>



from Angular: Changing font-size using css variables is applying but not reflecting in browser for certain fields

How to solve CSRF "Forbidden Cookie not set" error in Django?

I am using Angular 8 as frontend and Django 1.11.18 as backend. I am running my Angular project on https://127.0.0.1:4200 through command ng server --ssl true and Django API's are deployed on a separate redhat server and can be accessed through https://192.xxx.x.xx:7002/

My Login is a GET Request that returns success response with csrf token in header but cookies are not received on the browser at that time and when I call my POST request this cause "Forbidden" error due to CSRF Token.

Middleware in my settings.py is:

MIDDLEWARE = [
        'Common.customMiddleware.ProcessRequest',
        'django.middleware.security.SecurityMiddleware',
        'django.middleware.locale.LocaleMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'corsheaders.middleware.CorsMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
        
    ]

I have also added:

CSRF_TRUSTED_ORIGINS = ["127.0.0.1","192.xxx.x.xx"]

but still cookies are not received on the browser enter image description here

Any kind of help will be appreciated. One thing more I would like to mention is that When I deploy the Angular project on the same server on which Django API's are applied then application works fine.



from How to solve CSRF "Forbidden Cookie not set" error in Django?

Wednesday, 11 November 2020

ngx-monaco-editor - unable to force layout when container changes (using tab panel)

I am struggling with an instance of an ngx-monaco-editor inside a primeng tab panel which seems to 'lose' its size calculations when switching to another tab, changing the model value bound to the editor and then switching back to the initial tab again.

https://stackblitz.com/edit/primeng9-tabs-monaco-editor

Steps to replicate using url above:

  • The 'Editor' tab will be initially selected
  • Select 'Tab 2'
  • Click the 'change code' button
  • Change back to the 'Editor' tab and now see that the editor has shrunk in size

Before:

enter image description here

After:

enter image description here

Inspecting in the dom, the originally assigned style is still present.

As you can see from the source code in my sample app, I also tried using the editor's layout method in the tab change event to attempt to force a recalculation of the size based on the container but this has made no difference

Interestingly if I resize the window this does seem to trigger the editor component to resize again correctly.



from ngx-monaco-editor - unable to force layout when container changes (using tab panel)

Dynamically compiled lazy loaded dynamic routes in Angular causing 'unsafe-eval' error

In the index.html file of the angular application after applying the Content Security Policy, the application is giving 'unsafe-eval' console error as below -

core.js:4442 ERROR Error: Uncaught (in promise): EvalError: Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "default-src 'self'".

EvalError: Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "default-src 'self'".

    at new Function (<anonymous>)
    at JitEvaluator.evaluateCode (compiler.js:6740)
    at JitEvaluator.evaluateStatements (compiler.js:6714)
    at CompilerFacadeImpl.jitExpression (compiler.js:19300)
    at CompilerFacadeImpl.compileNgModule (compiler.js:19238)
    at Function.get (core.js:25864)
    at getNgModuleDef (core.js:1853)
    at new NgModuleFactory$1 (core.js:24270)
    at Compiler_compileModuleSync__POST_R3__ (core.js:27085)
    at Compiler_compileModuleAsync__POST_R3__ [as compileModuleAsync] (core.js:27090)
    at resolvePromise (zone-evergreen.js:798)
    at resolvePromise (zone-evergreen.js:750)
    at zone-evergreen.js:860
    at ZoneDelegate.invokeTask (zone-evergreen.js:399)
    at Object.onInvokeTask (core.js:27483)
    at ZoneDelegate.invokeTask (zone-evergreen.js:398)
    at Zone.runTask (zone-evergreen.js:167)
    at drainMicroTaskQueue (zone-evergreen.js:569)

This error is getting caused by using the compileModuleAsync() method from Compiler class as I am trying to build the module dynamically.

If I don't use the Content Security Policy, then the application works fine and it doesn't give such console error. Below is the policy details -

<meta http-equiv="Content-Security-Policy" content="default-src 'self';" />

As per the observation from callstack, the below function part of Angular Framework uses new Function() expression and leads to security issue -

 /**
     * Evaluate a piece of JIT generated code.
     * @param sourceUrl The URL of this generated code.
     * @param ctx A context object that contains an AST of the code to be evaluated.
     * @param vars A map containing the names and values of variables that the evaluated code might
     * reference.
     * @param createSourceMap If true then create a source-map for the generated code and include it
     * inline as a source-map comment.
     * @returns The result of evaluating the code.
     */
    evaluateCode(sourceUrl, ctx, vars, createSourceMap) {
        let fnBody = `"use strict";${ctx.toSource()}\n//# sourceURL=${sourceUrl}`;
        const fnArgNames = [];
        const fnArgValues = [];
        for (const argName in vars) {
            fnArgValues.push(vars[argName]);
            fnArgNames.push(argName);
        }
        if (createSourceMap) {
            // using `new Function(...)` generates a header, 1 line of no arguments, 2 lines otherwise
            // E.g. ```
            // function anonymous(a,b,c
            // /**/) { ... }```
            // We don't want to hard code this fact, so we auto detect it via an empty function first.
            const emptyFn = new Function(...fnArgNames.concat('return null;')).toString();
            const headerLines = emptyFn.slice(0, emptyFn.indexOf('return null;')).split('\n').length - 1;
            fnBody += `\n${ctx.toSourceMapGenerator(sourceUrl, headerLines).toJsComment()}`;
        }
        const fn = new Function(...fnArgNames.concat(fnBody));
        return this.executeFunction(fn, fnArgValues);
    }

This is the routes.json in which I am trying to build configuration written in the loadChildren -

{
      path: '',
      componentName: 'dummy',
      children: [
        {
          path: '',
          pathMatch: 'full',
          redirectTo: 'set-focus-action',
        },
        {
          path: 'set-focus-action',
          loadChildren: {
            routes: [
              {
                path: '',
                componentName: 'dynamicType1',
              },
            ],
          },
        },
      ],
    }

Below is the code to build the module -

private featureModule(loadChildren: string): Observable<Type<any>> {
    return this.getRoutes(loadChildren).pipe(
      switchMap((routesConfig) => {
        const module = NgModule(this.createFeatureModule(routesConfig))(
          class {}
        );
        return from(this.compiler.compileModuleAsync(module));
      }),
      map((m) => {
        return m.moduleType;
      })
    );
  }

Also, I am using JitCompilerFactory for this compiler -

{ provide: COMPILER_OPTIONS, useValue: {}, multi: true },
        {
          provide: CompilerFactory,
          useClass: JitCompilerFactory,
          deps: [COMPILER_OPTIONS],
        },
        {
          provide: Compiler,
          useFactory: createCompiler,
          deps: [CompilerFactory],
        }

Please let me know in-case any other details. Any suggestions would be really helpful.

Below is a link for stackblitz where this issue is getting reproducible https://stackblitz.com/github/HimanshuGoel/unsafe-eval-issue?file=src%2Findex.html

enter image description here

If I remove this CSP, it gets render correctly -

enter image description here



from Dynamically compiled lazy loaded dynamic routes in Angular causing 'unsafe-eval' error

Okta Access-token is returned undefined to Angular application deployed on AWS Cloudfront

I have integrated with okta recently and I am using @okta/okta-angular for angular.

In local everything is working fine. I am able to log in and the okta is redirecting correctly and the user is being authenticated.

but the same code is not working in the environment (https site) I have added URL to TRUSTED ORIGIN and also to logout and login URI in okta account.

In the ENVIRONMENT:

when I click on login it is redirecting me to okta. When Login is successful it is redirecting back to my application but when I console the access token and user authentication it is showing as undefined and false. (which is working fine in local)

 const accessToken =  await this.oktaAuth.getAccessToken();
   console.log('accessToken-----',accessToken);
    this.isAuthenticated =  await this.oktaAuth.isAuthenticated();
    console.log('this.isAuthenticated----',this.isAuthenticated);
    if (!!accessToken) {
      this.oktaAuth.getUser().then((claims:UserClaims) => {
        this.providerMARecord.emit(claims);
      });
    }


from Okta Access-token is returned undefined to Angular application deployed on AWS Cloudfront

Is it ok to use the function Map.prototype.get() inside an Angular Template Expression?

I know that you should never use function calls within Angulars Template Expressions, otherwise they will be called permanently and the app will be extremely stressed. (see Medium - Why You Should Never Use Function Calls In Angular Template Expressions)

I also know that it is ok, when the []-array-operator is used. e.g.

<div *ngIf="array[i]"></div>

Does anyone know if it is ok to use the function Map.prototype.get() inside a template expression like this?

<!-- the Map is structured like Map<Object, Object[]> -->
<ng-container *ngFor="let elem of someMap.get(keyToAnArray)">
    <app-some-compo [elem]="elem"></app-some-compo>
</ng-container>


from Is it ok to use the function Map.prototype.get() inside an Angular Template Expression?

Tuesday, 10 November 2020

Inject query parameter into dependency provider factory in Angular

I want a value from the window.location search parameters passed to the body of a dependency provider factory, ideally in an idiomatic Angular way.

Use case: writing my first Angular app I have the app running on one port and the backend server on another. I want to append &backend=localhost:12345 to the URL to have the app talk to that host. This is read-only, hand-written to the URL bar. I don't want to navigate to such a URL.

Approaches considered:

  1. Use window.location.href directly. Makes the code depend on a browser, potentially breaking test fixtures or anything else that wants to execute the code outside a browser.
  2. Use PlatformLocation.href. The doc says “this class should not be used directly by an application developer.”
  3. Use Location.path(). Seems to work, but also seems to not offer any way to access the full URL. The stand-alone path includes the query parameter, but appears to be invalid as an argument to the URL constructor, so I ended up with something like new URL('http://no-such-host/' + location.path()).searchParams.get('backend'). Hardly elegant.
  4. Use ActivatedRoute.queryParams somehow. Injecting an ActivatedRoute into my factory apparently gives me a default instance (stringifies as Route(url:'', path:'')) so the query parameters seem to be absent. And the queryParams method returns an Observable, while from what I read on the net, using asynchronous code flow for a provider factory is tricky at best.

Is there a better way to let a factory make decisions based on a query parameter?



from Inject query parameter into dependency provider factory in Angular

Monday, 9 November 2020

Angular SSR build on different route

I have angular 9 app running on ssr (universal expressjs). The application should be on a specific route: example.com/app

I'm using APP_BASE_HREF as '/app' to have all angular routings correctly but the build files are still on the root. If I add "deployUrl": "/app/" to the build options as well as the server options, I see the request to build files include /app -> /app/main-es2015.js but the files themselves are still on the root.

What do I need to do to fix that?

This is how server.ts looks like:

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';
import { enableProdMode } from '@angular/core';

enableProdMode()

// The Express app is exported so that it can be used by serverless Functions.
export function app() {
  const server = express();
  const distFolder = join(process.cwd(), 'dist/browser');
  const indexHtml = existsSync(join(distFolder, 'index.original.html')) ? 'index.original.html' : 'index';

  server.engine('html', ngExpressEngine({
    bootstrap: AppServerModule,
  }));

  server.set('view engine', 'html');
  server.set('views', distFolder);

  // 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() {
  const port = process.env.PORT || 4200;

  // Start up the Node server
  const server = app();

  var helmet = require('helmet')
  server.use(helmet());

  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';

Here is the angular.json file as well:

{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "version": 1,
  "newProjectRoot": "projects",
  "projects": {
    "project1": {
      "projectType": "application",
      "schematics": {
        "@schematics/angular:component": {
          "style": "scss"
        }
      },
      "root": "",
      "sourceRoot": "src",
      "prefix": "app",
      "architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:browser",
          "options": {
            "outputPath": "dist/browser",
            "index": "src/index.html",
            "main": "src/main.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "tsconfig.app.json",
            "aot": true,
            "assets": [
              "src/favicon.ico",
              "src/assets"
            ],
            "styles": [
              "src/styles.scss",
              "./node_modules/bootstrap/dist/css/bootstrap.css",
              "./node_modules/ngx-toastr/toastr.css",
              "./node_modules/@fortawesome/fontawesome-free/css/all.css"
            ],
            "scripts": [
              "./node_modules/jquery/dist/jquery.js",
              "./node_modules/bootstrap/dist/js/bootstrap.js"
            ]
          },
          "configurations": {
            "production": {
              "fileReplacements": [
                {
                  "replace": "src/environments/environment.ts",
                  "with": "src/environments/environment.prod.ts"
                }
              ],
              "optimization": true,
              "outputHashing": "all",
              "sourceMap": false,
              "extractCss": true,
              "namedChunks": false,
              "extractLicenses": true,
              "vendorChunk": false,
              "buildOptimizer": true,
              "budgets": [
                {
                  "type": "initial",
                  "maximumWarning": "2mb",
                  "maximumError": "5mb"
                },
                {
                  "type": "anyComponentStyle",
                  "maximumWarning": "6kb",
                  "maximumError": "10kb"
                }
              ]
            },
            "staging": {
              "fileReplacements": [
                {
                  "replace": "src/environments/environment.ts",
                  "with": "src/environments/environment.staging.ts"
                }
              ],
              "optimization": true,
              "outputHashing": "all",
              "sourceMap": false,
              "extractCss": true,
              "namedChunks": false,
              "aot": true,
              "extractLicenses": true,
              "vendorChunk": false,
              "buildOptimizer": true,
              "budgets": [
                {
                  "type": "initial",
                  "maximumWarning": "2mb",
                  "maximumError": "5mb"
                }
              ]
            }
          }
        },
        "serve": {
          "builder": "@angular-devkit/build-angular:dev-server",
          "options": {
            "browserTarget": "project1:build"
          },
          "configurations": {
            "production": {
              
              "browserTarget": "project1:build:production"
            },
            "staging": {
              "browserTarget": "project1:build:staging"
            },
          }
        },
        "extract-i18n": {
          "builder": "@angular-devkit/build-angular:extract-i18n",
          "options": {
            "browserTarget": "project1:build"
          }
        },
        "test": {
          "builder": "@angular-devkit/build-angular:karma",
          "options": {
            "main": "src/test.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "tsconfig.spec.json",
            "karmaConfig": "karma.conf.js",
            "assets": [
              "src/favicon.ico",
              "src/assets"
            ],
            "styles": [
              "src/styles.scss"
            ],
            "scripts": []
          }
        },
        "lint": {
          "builder": "@angular-devkit/build-angular:tslint",
          "options": {
            "tsConfig": [
              "tsconfig.app.json",
              "tsconfig.spec.json",
              "e2e/tsconfig.json"
            ],
            "exclude": [
              "**/node_modules/**"
            ]
          }
        },
        "e2e": {
          "builder": "@angular-devkit/build-angular:protractor",
          "options": {
            "protractorConfig": "e2e/protractor.conf.js",
            "devServerTarget": "project1:serve"
          },
          "configurations": {
            "production": {
              "devServerTarget": "project1:serve:production"
            },
            "staging": {
              "devServerTarget": "project1:serve:staging"
            }
          }
        },
        "server": {
          "builder": "@angular-devkit/build-angular:server",
          "options": {
            "outputPath": "dist/server",
            "main": "server.ts",
            "tsConfig": "tsconfig.server.json"
          },
          "configurations": {
            "production": {
              "outputHashing": "media",
              "fileReplacements": [
                {
                  "replace": "src/environments/environment.ts",
                  "with": "src/environments/environment.prod.ts"
                }
              ],
              "sourceMap": false,
              "optimization": true
            },
            "staging": {
              "outputHashing": "media",
              "fileReplacements": [
                {
                  "replace": "src/environments/environment.ts",
                  "with": "src/environments/environment.staging.ts"
                }
              ],
              "sourceMap": false,
              "optimization": true
            }
          }
        },
        "serve-ssr": {
          "builder": "@nguniversal/builders:ssr-dev-server",
          "options": {
            "browserTarget": "project1:build",
            "serverTarget": "project1:server"
          },
          "configurations": {
            "production": {
              "browserTarget": "project1:build:production",
              "serverTarget": "project1:server:production"
            },
            "staging": {
              "browserTarget": "project1:build:staging",
              "serverTarget": "project1:server:staging"
            }
          }
        },
        "prerender": {
          "builder": "@nguniversal/builders:prerender",
          "options": {
            "browserTarget": "project1:build:production",
            "serverTarget": "project1:server:production",
            "routes": [
              "/"
            ]
          },
          "configurations": {
            "production": {}
          }
        }
      }
    }},
  "defaultProject": "project1"
}

I run it by:

ng build && ng run project1:server:staging && node dist/server/main.js


from Angular SSR build on different route

Newly added options in existing select control is not reflecting in view in angular

I have initialized a list of options for my DDL and later I want to add some more options to the same DDL. In the console, it shows that those options are added but in view, it's not reflecting the changes.

Below is my code and explanations:

  1. Initialized the list (Select with optgroup)
this.optList1 = [
    {
        "RuleId": 104,
        "RuleName": "Rule 104",
        "IsActive": true,
    },
    {
        "RuleId": 105,
        "RuleName": "Rule 105",
        "IsActive": true,
    }
];

this.optGroup = [];
const obj1 = {
    name: 'Group 1',
    rule: this.optList1
};
this.optGroup.push(obj1);
  1. Later in some function call I'm adding some more options in the same DDL
this.optList2 = [
    {
        "RuleId": 111,
        "RuleName": "Rule 111",
        "IsActive": true,
    },
    {
        "RuleId": 112,
        "RuleName": "Rule 112",
        "IsActive": true,
    }
];
const obj2 = {
    name: 'Group 2',
    rule: this.optList2
};
this.optGroup.push(obj2);

Here is HTML:

<mat-form-field>
    <mat-select formControlName="rules" multiple [compareWith]="compareRule">
        <mat-optgroup *ngFor="let group of optGroup" [label]="group.name">
            <ng-container *ngIf="group.name == 'Group 1'">
                <mat-option *ngFor="let rule of group.rule" [value]="rule"></mat-option>
            </ng-container>
            <ng-container *ngIf="group.name == 'Group 2'">
                <mat-option *ngFor="let rule of group.rule" [value]="rule"></mat-option>
            </ng-container>
        </mat-optgroup>
    </mat-select>
</mat-form-field>

All the options are showing in the console but not reflecting in view.



from Newly added options in existing select control is not reflecting in view in angular

how to convert ajax post call api in angular8

Client given below Ajax call to post the data to there server, but I am not able to understand how to convert this call into component.ts and servervice

 <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
 <script type="text/javascript">
 $.ajax
 ({
  type: "POST",
  url: 'https://xyz/client/schedule',
  contentType: 'application/json',
  data: JSON.stringify({
    "apiKey": "myapikey"
  }),
  dataType : 'json',
  headers: {
  'authorization': '<?php echo $authorization; ?>'
  },
  success: function(retval)
  {
  // alert(retval);
  console.log(retval);
  // var success = retval.success;
  }
  });
  </script>

I have updated Question and added after two replied answer

Below is my model class

export class Schedule1 {

classTitle: string;
classInfo: string;
classDateTime: string;
timezone: string;
classDuration: number;
classRecording:string;
classAutoStart: boolean;
recordingAutoStart: boolean;
classVideoRes: number;
    
   constructor() {
    
      
   }

  }

Below is component.ts on button click passing static values

import { Schedule1 } from '../Models/Schedule1.model'


   Schedule1: Schedule1 = new Schedule1();

    addSchedule(scheduleForm: NgForm): void {

    //static data parameter passing
    this.Schedule1.classTitle='hi Class on 3rd April, 2020';
    this.Schedule1.classInfo= 'This is a demo class scheduled to understand API';
    this.Schedule1.classDateTime= '2020-11-12 11:30 AM';
    this.Schedule1.timezone= 'Asia/Kolkata';
    this.Schedule1.classDuration= 15;
    this.Schedule1.classRecording= 'yes';
    this.Schedule1.classAutoStart= false;
    this.Schedule1.recordingAutoStart= false;
    this.Schedule1.classVideoRes= 720;


    //const data = JSON.stringify(this.Schedule1);
    const data = { 
    apiKey: "dcbf187d-bdfe-431b-8f60-fa19bf51cd85", 
    data:  JSON.stringify(this.Schedule1)
    } 

    this.subscription = this.userSvc
    .fetchData("https: //xyz.com/client/schedule", data)
    .subscribe(
    data => {
    // Data on Success
    console.log("data", data);
    },
    error => {
    console.log("error", error);
    }
    );

    }

Below is service.ts

  fetchData(url: string, data: any): Observable<any> {
    const headers = {
    
    Authorization: "Bearer "+"1234",
     "My-Custom-Header": "foobar",
    contentType: "application/json"
    };

   return this.http.post(url, data, {
    headers
    });
   }

in console getting this error.

enter image description here



from how to convert ajax post call api in angular8

Sunday, 8 November 2020

Angular: Change Font Size options for users in IE11 (CSS-Variables)

I am developing an Angular application. From the webpage, the user can select a small, medium or large fonts (medium is the default) and based on that we have to change the font size all over the page. Now for other browsers, I can use var() but it is not compatible with IE. So one way of doing it is manually applying font-size in every single HTML tags either using ngStyle or ngClass. But I find this method really bad. Is there another way of doing it? I don't want to write this piece of code in every single component.

<div class="hm-header-title" [ngStyle]="fontSize()"></div>
fontSize(){
    return this.ieStyleService.fontSize() // ex return {'font-size': '11px'}
}


from Angular: Change Font Size options for users in IE11 (CSS-Variables)

Saturday, 7 November 2020

Angular CDK connect overlay with scroll to container

(First post here, so bear with me)

I have a table inside a container where I display an icon for rows that meet certain criterias. Clicking the icon should open an overlay to display some information, and the overlay should stay open even if I scroll inside the container. The scroll initially followed the body of the page, so I started creating a custom strategy. However, I cannot get it to follow the table scroll. The overlay sticks in one place and does not move accordingly.

Overlay is generated as below. Any tips on how this is generally solved would be appreciated!

private createOverlay() {
    const positionStrategy = this.overlay.position()
      .flexibleConnectedTo(this.overlayorigin.elementRef)
      .withFlexibleDimensions(false)
      .withPush(false)
      .withPositions([
        {
          originX: 'start',
          originY: 'bottom',
          overlayX: 'start',
          overlayY: 'top'
        },
        {
          originX: 'start',
          originY: 'top',
          overlayX: 'start',
          overlayY: 'bottom',
        }]);

    const overlayConfig = new OverlayConfig({
      hasBackdrop: false,
      scrollStrategy: this.overlay.scrollStrategies.reposition({autoClose: false}),
      positionStrategy: positionStrategy
    });


    this._overlayRef = this.overlay.create(overlayConfig);
    this._overlayRef.backdropClick().subscribe(_ => {
      this._overlayRef.detach();
      this.closeWarning.emit(true);
    });

    this._portal = new TemplatePortal(this.content, this.portal);
    this._overlayRef.attach(this._portal);
}


from Angular CDK connect overlay with scroll to container

Friday, 6 November 2020

Issue with socket.io-stream importation in Angular 6

I'm using npm install socket.io-stream I implemented socket.io-stream on my angular component like this :

import * as io from 'socket.io-client';
import * as ss from 'socket.io-stream';

I just want to create a duplex stream like this :

stream=ss.createStream();

I have this error when I run ng build :

ERROR in ./node_modules/socket.io-stream/lib/iostream.js
Module not found: Error: Can't resolve 'stream' in ' 
'C:\Users\geoffroy\Documents\Mines Alès\2A\Stage\WebService based 
GUI\WebApp\node_modules\socket.io-stream\lib'
ERROR in ./node_modules/socket.io-stream/lib/blob-read-stream.js
Module not found: Error: Can't resolve 'stream' in 
'C:\Users\geoffroy\Documents\Mines Alès\2A\Stage\WebService based 
GUI\WebApp\node_modules\socket.io-stream\lib'

I don't understand because on my server.js It seems to work..

I try to run the command npm install stream and I don't have error with ng build. But when I launch my application I have a new error in my browser console :

inherits_browser.js:5 Uncaught TypeError: Cannot read property 'prototype' of undefined
at Object.inherits (inherits_browser.js:5)
at Object../node_modules/socket.io-stream/lib/iostream.js (iostream.js:10)
at __webpack_require__ (bootstrap:76)
at Object../node_modules/socket.io-stream/lib/socket.js (socket.js:4)
at __webpack_require__ (bootstrap:76)
at Object../node_modules/socket.io-stream/lib/index.js (index.js:1)
at __webpack_require__ (bootstrap:76)
at Object../node_modules/socket.io-stream/index.js (index.js:2)
at __webpack_require__ (bootstrap:76)

Thanks for your help



from Issue with socket.io-stream importation in Angular 6

Thursday, 5 November 2020

Maintain scroll position with CDK autosize virtual scoll strategy

Maintain scroll position with CDK autosize virtual scoll strategy

I have a large list of items that can be scrolled with <cdk-virtual-scroll-viewport autosize> provided by @angular/cdk-experimental (the items have dynamic heights, thus I'm using this scroll strategy instead of the FixedSizeVirtualScrollStrategy).

New items are inserted in the list over time, i.e. they are appended on top. When the user scrolls down I want to avoid that new items will push the items in the viewport away. Therefore I need a mechanism to maintain / restore the scroll position after the items have been added.

I have a semi-working solution (and hacky because it reads private fields), but the viewport shifts a few pixels randomly after items have been added.

Here are the relevant code parts:

@ViewChild(CdkVirtualScrollViewport) viewport: CdkVirtualScrollViewport;

...

// After new items have been added:

const offset = this.viewport.measureScrollOffset('top');
const topPosition = offset + newItems.length * this.viewport['_scrollStrategy']._averager._averageItemSize; // the autosize strategy determines an average item size I'm trying to use to determine how the viewport should be shifted

this.viewport.scrollTo({
  top: topPosition
});

I created a demo of this approach here: https://stackblitz.com/edit/angular-be926g?file=src/app/cdk-virtual-scroll-overview-example.ts

Any ideas how to achieve this seamlessly with a constant viewport?



from Maintain scroll position with CDK autosize virtual scoll strategy

Lambda@Edge function not being called on Cloudfront error page

I have an Angular app's static files being served on an S3 bucket through Cloudfront. My Cloudfront distribution has error pages set up so it still renders the Angular's index.html. This means that if I request <cloudfront-distribution>.cloudfront.net/home-page, instead of saying that it didn't find a file named home-page on the S3 bucket, it will still render the angular app and the angular app will handle that /home-page route.

I needed to include some security headers on the app server so I set up a Lambda@Edge function to inject those headers on a viewer response event (like described here https://aws.amazon.com/blogs/networking-and-content-delivery/adding-http-security-headers-using-lambdaedge-and-amazon-cloudfront/).

The Lambda@Edge is working for routes that actually correspond to a file in the S3 bucket (if I have a file called image.png on the root folder of my S3 bucket, and I request <cloudfront-distribution>.cloudfront.net/image.png, I see the response headers that I injected via the Lambda@Edge function. The issue is when accessing a route that doesn't correspond to a file in the S3 bucket. If I access <cloudfront-distribution>.cloudfront.net/home-page, S3 will return a 404, Cloudfront will handle the 404 and act accordingly to the Error Pages configuration, i.e., respond with a 200 status code and render the index.html file. And when this happens, I don't see any of the headers I injected via the Lambda@Edge function, while all the other script files of my Angular app have the headers.

How can I make all responses go throught the Lambda@Edge function?



from Lambda@Edge function not being called on Cloudfront error page

Wednesday, 4 November 2020

Angular Splitting Object of Array in A4 pages it is working weird and not as excepted

This question it is a continue of the last question. My last question in Stackoverflow
I am trying to create some A4 pages within the Objects that I have in the json file. The last guys which answered me it, imediately stopped when I approved the answer. But the case here it is I need your help to help me further with my problem. The problem it is that, when the text in one property it is larger then the A4 page the directive it doesn't add new page in realtime but only in reload. I have for example in my json tree like this. Category -> SubCategory -> Properties. So i need to check if the Category it is larger then A4, if the SubCategory is larger and if the property is larger as the height of A4. I am trying to create something like Xing.
https://lebenslauf.com/ The design it look the same but instead editing in the page I have the edit logic in the modals

Here is the code what I have tried till now.

All for A4 pages

<!-- display: none style will any child that does not have #pageContent local variable defined -->
<div class="content-wrapper" #contentWrapper style="display: block">
  <ng-content></ng-content>
</div>
<div class="paginated-view" #paginatedView>

</div>

export class PaginatedViewComponent implements AfterViewInit {
  @Input() pageSize: "A3" | "A4" = "A4";

  @ViewChild("paginatedView") paginatedView: ElementRef<HTMLDivElement>;

  @ViewChild("contentWrapper") contentWrapper: ElementRef<HTMLDivElement>;

  @ContentChildren(PageContentDirective, { read: ElementRef })
  elements: QueryList<ElementRef>;

  constructor(private changeDetector: ChangeDetectorRef ) {}

  ngAfterViewInit(): void {
    this.updatePages();

    // when ever childs updated call the updatePagesfunction
    this.elements.changes.subscribe((el) => {
      this.updatePages();
    });
  }


  updatePages(): void {
    // clear paginated view
    this.paginatedView.nativeElement.innerHTML = "";

    // get a new page and add it to the paginated view
    let page = this.getNewPage();
    this.paginatedView.nativeElement.appendChild(page);

    let lastEl: HTMLElement;
    // add content childrens to the page one by one
    this.elements.forEach((elRef) => {
      const el = elRef.nativeElement;

      // if the content child height is larger than the size of the page
      // then do not add it to the page

      if (el.clientHeight > page.clientHeight) {
        return;
      }
      // add the child to the page
      page.appendChild(el);

      // after adding the child if the page scroll hight becomes larger than the page height
      // then get a new page and append the child to the  new page
      if (page.scrollHeight > page.clientHeight) {
        page = this.getNewPage();
        this.paginatedView.nativeElement.appendChild(page);
        page.appendChild(el);
      }
      lastEl = el;
    });
    this.changeDetector.detectChanges();

    // bring the element in to view port
   // lastEl.scrollIntoView({ behavior: "smooth", block: "nearest" });
  }

  getNewPage(): HTMLDivElement {
    const page = document.createElement("div");
    page.classList.add("page");
    page.classList.add(this.pageSize);
    return page;
  }
}
    @Directive({
  // tslint:disable-next-line: directive-selector
  selector: "[pageContent]"
})
export class PageContentDirective {

}

This is my HTML when I try to show data

   <div style="transition: transform 0.25s ease 0s;transform: scale(1.3);transform-origin: 50% 0px 0px;backface-visibility: hidden;perspective: 1000px;display: block;margin: 0px 11.5385%;font-size:10px;width: 76.9231%;-webkit-font-smoothing: antialiased;">
<app-paginated-view [pageSize]="'A4'" *ngIf="model" class="Grid-grid-column">
  <div pageContent class="row">
    <div class="col col-lg-7">
      <h4> </h4>
    </div>
    <div class="col text-right">
      <input type="file" accept="image/*" (change)="readUrl($event)">
      <img [src]="url" (change)="readUrl($event)" height="128" style="cursor:  pointer">

    </div>
  </div>

  <div pageContent class="Unit-unit-unitGroup"
   *ngFor="let personalData of model.personalData; let id = index">
   <div pageContent [ngClass]="{ 'isCatActive': selectedCategory === category.PersonalData}">

   <ng-container *ngIf="selectedCategory === category.PersonalData" clickOutside (clickOutside)="removeClick()">
    <ul>
      <li class="fa fa-plus addIconTop" (click)="openDialog()"></li>
      <li class="fa fa-plus addIconBottom" (click)="openDialog()"></li>
      <li class="fa fa-trash deleteIconRight" (click)="deleteCategory(index)"></li>
      <li class="fa fa-arrow-down moveIconDown"></li>
      <li class="fa fa-arrow-up moveIconTop"></li>
    </ul>
  </ng-container>

    <div pageContent class="col-md-12" (click)="setCategory(category.PersonalData)">
      <div class="row height">
      <div  class="col-md-4 col-sm-6 text-right tLine"></div>
      <h3 class="first-template-paragraphTitle Paragraph-paragraph-title height">
        <div class="Text-text-wrapper">
          <div class="Text-Text-text">category.PersonalData</div>
        </div>
      </h3>
    </div>
    </div>
    <div pageContent class="container-fluid">
      <ng-container>
      <app-personal-data [personalData]="personalData" [model]="model" [id]="id">
    </app-personal-data>
  </ng-container>
  </div>
  </div>
  </div>

    <!-- Career Component -->
    <ng-container *ngFor="let careers of model.careers" class="Unit-unit-unitGroup">
      <div pageContent class="col-md-12">
        <div class="row height">
        <div  class="col-md-4 col-sm-6 text-right tLine"></div>
        <h3 class="first-template-paragraphTitle Paragraph-paragraph-title height">
          <div class="Text-text-wrapper">
            <div class="Text-Text-text">category.Career</div>
          </div>
        </h3>
      </div>
      </div>
      <div class="container-fluid" pageContent>
      <ng-container *ngFor="let careerObj of careers.subCategories; let i = index">
      <app-career [careerObj]="careerObj" [id]="i" [career]="careers" [model]="model"></app-career>
      </ng-container>
      <ng-container *ngFor="let emptyObj of careers.emptySubContents; let iEmpty = index">
        <app-empty-object [emptyObj]="emptyObj" [iEmpty]="iEmpty" [model]="model" [isFromCareer]="true"></app-empty-object>
      </ng-container>
        </div>
    </ng-container>

    <!--Education Component-->
    <ng-container *ngFor="let education of model.education" class="Unit-unit-unitGroup">
      <div pageContent [ngClass]="{ 'isCatActive': selectedCategory === category.Education}">
        <ng-container *ngIf="selectedCategory === category.Education" clickOutside (clickOutside)="removeClick()">
          <ul>
            <li class="fa fa-plus addIconTop" (click)="openDialog()"></li>
            <li class="fa fa-plus addIconBottom" (click)="openDialog()"></li>
            <li class="fa fa-trash deleteIconRight" (click)="deleteCategory(index)"></li>
            <li class="fa fa-arrow-down moveIconDown"></li>
            <li class="fa fa-arrow-up moveIconTop"></li>
          </ul>
        </ng-container>
      <div pageContent class="col-md-12" (click)="setCategory(category.Education)">
        <div class="row height">
          <div class="col-md-4 col-sm-6 text-right tLine"></div>
          <h3 class="first-template-paragraphTitle Paragraph-paragraph-title height">
            <div class="Text-text-wrapper">
              <div class="Text-Text-text">category.Education</div>
            </div>
          </h3>
      </div>
      </div>
      <div pageContent class="container-fluid">
      <ng-container *ngFor="let educationObj of education.subCategories; let i = index" class="col-md-12">
        <app-education [educationObj]="educationObj" [id]="i" [education]="education" [model]="model"></app-education>
      </ng-container>
      </div>
      </div>
    </ng-container>


  <!-- Skills Component-->
    <ng-container *ngFor="let skills of model.skills" class="Unit-unit-unitGroup">
    <div pageContent [ngClass]="{ 'isCatActive': selectedCategory === category.Skills}">
    <ng-container clickOutside *ngIf="selectedCategory === category.Skills" (clickOutside)="removeClick()">
      <ul>
        <li class="fa fa-plus addIconTop" (click)="openDialog()"></li>
        <li class="fa fa-plus addIconBottom" (click)="openDialog()"></li>
        <li class="fa fa-trash deleteIconRight" (click)="deleteCategory(index)"></li>
        <li class="fa fa-arrow-down moveIconDown"></li>
        <li class="fa fa-arrow-up moveIconTop"></li>
      </ul>
    </ng-container>
    <div pageContent class="col-md-12" (click)="setCategory(category.Skills)">
      <div class="row height">
        <div class="col-md-4 col-sm-6 text-right tLine"></div>
        <h3 class="first-template-paragraphTitle Paragraph-paragraph-title height">
          <div class="Text-text-wrapper">
            <div class="Text-Text-text">category.Skills</div>
          </div>
        </h3>
    </div>
    </div>
          <div pageContent class="container-fluid">
      <ng-container *ngFor="let skillObj of skills.subCategories; let i = index" class="col-md-12">
        <app-skills [skillObj]="skillObj" [id]="i" [skills]="skills" [model]="model"></app-skills>
      </ng-container>
      </div>
    </div>
  </ng-container>


</app-paginated-view>
</div>

And this is the css

.A4 {
  width: 595px;
  height: 842px;
  padding: 25px 25px;
  position: relative;
}

If you want to see more code, here is the stackblitz.

Stackblitz

And here is the screenshot which is the current design. As you can see here the space in the Career it is very large it should not be like that. It should add the text based on the height and if is alrger then cut the text and the other text add to new page. enter image description here



from Angular Splitting Object of Array in A4 pages it is working weird and not as excepted

Tuesday, 3 November 2020

Angular Interface for Service in HTML Selector

How do I provide Dependency Injection through a HTML Selector? Following answer is through typescript.

https://stackoverflow.com/a/40068594/14432516

providers: [
  { provide: ISearchService, useValue: SearchInFemaleEmployeeService}
]

I want to do something similar in html from Parent, and use Male/Female Employee Search Service. Parent component has this html.

<app-search-component>
</app-search-component>

I read it can be done through Module? However, this Module calls Search Component many times in html, and may require Male Or FemaleEmployee Search Service.



from Angular Interface for Service in HTML Selector

Monday, 2 November 2020

Google autocomplete dropdown position issue

I'm using NgxAutocomPlace module in my Angular App, the following module work with google autocomplete API by generating .pac-container in which it shows autocomplete results.

The issue is that on mobile the dropdown goes above instead of below of the input and it's unusable for the final user, it looks like this:

enter image description here

And here is how's my code looks like:

<div class="container-indirizzo mb-3">
  <label>Indirizzo di consegna</label>
  <div class="inside-indirizzo">
      <div class="indirizzo">
        <input
          *ngIf="addressOptions !== null"
          type="text"
          class="form-control"
          required
          placeholder="es. Via Disraeli"
          formControlName="indirizzo"
          ngxAutocomPlace
          [options]="addressOptions"
          (selectedPlace)="addressChange($event)"
        />
      </div>
      <div class="civico" *ngIf="isCivico">
        <input type="text" class="form-control" formControlName="nciv" placeholder="N°" autofocus />
      </div>
  </div>
</div>

Is there a way to set the position of that dropdown under the <input>?



from Google autocomplete dropdown position issue

Angular Interceptor With Subscribe Not WorkingProperly

Hi I have created an interceptor to refresh the token if token expires. Everything is fine except that when token expires before all the interceptor subscribe method gets executed the calling function throws an error.

this._customerService.getCustomers(this._customerSearchComp).subscribe(
  (data:any) => {
    
    }
  },
  (error) => {
    this.loader = false;  
    console.log("Inside error while retrieving customer");    
    this.notifyService.openSnackBar('error Thrown' + error, 'snackbar-warning');//this error is thrown before the interceptor subscribe method works
  }

And Here is my interceptor.

return next.handle(request).do((event: HttpEvent<any>) => {
  if (event instanceof HttpResponse) {
  }
}, async (err: any) => {
  if (err instanceof HttpErrorResponse) {
   if (err.status === 401) {
      debugger;
      let token = this._tokenService.getAuthToken();
      let refreshToken=this._tokenService.getRefreshToken(); 


      return this._authenticationService
        .refreshToken({
          token: token,
          refreshToken: refreshToken,
        })
        .subscribe(
          (data: any) => {
            debugger;
            console.log("Token Refreshed");
            this._tokenService.setToken(data.token);
            this._tokenService.setRefreshToken(data.refreshToken);
             this._tokenService.setRefreshToken(data.refreshToken);
            request = request.clone({
              headers: request.headers.set(
                'Authorization',
                'Bearer ' + data.token
              ),
            });

            return next.handle(request);
          },
          (error) => {
            this.dialogRef.closeAll();
            this.notifyService.isTokenExpired=true;
            this._router.navigate(['/']);
          }
        );
      
      }
    }
  });


from Angular Interceptor With Subscribe Not WorkingProperly

Angular remember the latest input data in searching fields and search result

I wanna store the latest input data that users fill out the search form either the search result, in order when users shift to another page and they back the data stored still there. The first thing come up into my mind is save it into localStorage. I'm wondering have any other way to archive this?



from Angular remember the latest input data in searching fields and search result