Categories
discuss

How to prevent status bar from covering modal page in nativescript

i’m having an issue with my nativescript app
The content of the modal page is pushed behind the status-bar and the status-bar covers it.
I’ve worked with nativescript on a previous project and i didn’t have this issue with my modal pages.

I have downloaded and implemented these plugins but it had no effect

Nativescript-status-bar

Natvescript-statusbar

This is how it currently appears

This is how it currently appears

Answer

I fixed it by removing this <item name="android:windowTranslucentStatus">true</item> from App_resources/Android/src/main/res/values/styles.xml

you can also check App_resources/Android/src/main/res/values21/styles.xml to be sure its not there also

Categories
discuss

eslint complaining about resolving paths

I keep receiving the eslint error import/no-unresolved and am unsure as to how I fix it. I know this is related to babel, but I’m not sure how to get babel and eslint to play nice.

My babel.config.js file:

module.exports = {
  presets: [['@babel/preset-env', { targets: { node: 'current' } }], '@babel/preset-react'],
  plugins: [
    'babel-plugin-macros',
    '@babel/plugin-syntax-dynamic-import',
    '@babel/plugin-transform-destructuring',
    [
      '@babel/plugin-proposal-class-properties',
      {
        loose: true,
      },
    ],
    [
      '@babel/plugin-proposal-object-rest-spread',
      {
        useBuiltIns: true,
      },
    ],
    [
      '@babel/plugin-transform-runtime',
      {
        helpers: false,
        regenerator: true,
      },
    ],
    [
      '@babel/plugin-transform-regenerator',
      {
        async: false,
      },
    ],
  ],
};

… and my .eslintrc.js file

module.exports = {
  parser: 'babel-eslint',
  extends: 'airbnb',
  env: {
    browser: true,
    node: true,
    jest: true,
    es6: true,
  },
  plugins: ['react', 'jsx-a11y'],
  parserOptions: {
    ecmaVersion: 6,
    sourceType: 'module',
    ecmaFeatures: {
      jsx: true,
    },
  },
  rules: {
    'object-curly-spacing': 2,
    'arrow-parens': ['error', 'as-needed'],
    'arrow-body-style': [2, 'as-needed'],
    'comma-dangle': [2, 'always-multiline'],
    'import/imports-first': 0,
    'import/newline-after-import': 0,
    'import/no-dynamic-require': 0,
    'import/no-extraneous-dependencies': 0,
    'import/no-named-as-default': 0,
    'import/no-unresolved': 2,
    'import/prefer-default-export': 0,
    indent: [
      2,
      2,
      {
        SwitchCase: 1,
      },
    ],
    'space-before-function-paren': 0,
    'jsx-a11y/aria-props': 2,
    'jsx-a11y/heading-has-content': 0,
    'jsx-a11y/label-has-associated-control': 2,
    'jsx-a11y/mouse-events-have-key-events': 2,
    'jsx-a11y/no-autofocus': 0,
    'jsx-a11y/role-has-required-aria-props': 2,
    'jsx-a11y/role-supports-aria-props': 2,
    'max-len': 0,
    'newline-per-chained-call': 0,
    'no-confusing-arrow': 0,
    'no-console': 1,
    'no-use-before-define': 0,
    'prefer-template': 2,
    'class-methods-use-this': 0,
    'react/forbid-prop-types': 0,
    'react/jsx-first-prop-new-line': [2, 'multiline'],
    'react/jsx-filename-extension': 0,
    'react/prefer-stateless-function': 0,
    'react/jsx-no-target-blank': 0,
    'react/require-extension': 0,
    'react/prop-types': 0,
    'react/self-closing-comp': 0,
    'require-yield': 0,
    'import/no-webpack-loader-syntax': 0,
    semi: ['error', 'always'],
  },
  settings: {
    'import/resolver': {
      webpack: {
        config: 'config/webpack/development.js',
      },
    },
  },
};

The issue occurs for every type of import: screenshot of eslint errors

Any suggestions?

EDIT

I’ve created a repository using the same eslint setup as I’m using in this project. It’s showing the same error I’m seeing.

https://github.com/brandondurham/eslint-test

Answer

You’ll have to at the very least update your eslint config to say you want ES2018 (or newer) support, since you’re validating modern JS with module imports:

module.exports = {
  ...
  parserOptions: {
    ecmaVersion: 2018,
    sourceType: 'module',
    ecmaFeatures: {
      jsx: true,
    },
  },
  ...
};

Because from https://eslint.org/docs/user-guide/configuring#specifying-parser-options we know that ecmaVersion: 6 corresponds to asking ESLint to validate your code as ES2015, which predates ES modules, and so will correctly flag any import ... from "..." statement as an error.

I tried your github repo with a heavily reduced ESlint config:

module.exports = {
  parser: 'babel-eslint',
  extends: 'airbnb',
  env: {
    browser: true,
    node: true,
    jest: true,
    es6: true
  },
  plugins: ['react'],
  parserOptions: {
    ecmaVersion: 2018,
    sourceType: 'module',
    ecmaFeatures: {
      jsx: true,
    },
  },
  rules: {
    'no-unused-vars': 0
  }
};

And that works just fine, so: start building it back up until it breaks, so you have a better idea of what really needs addressing.

Categories
discuss

Do TypeScript and typescript-eslint have overlapping purposes?

I was reading the typescript-eslint docs and I came into this section:

TypeScript and ESLint have similar purposes
This means that there will be cases where TypeScript actually solves a problem for us that we previously relied on ESLint for.

Having their definition in mind, one is a statically typed language and one is a tool that parses code and puts some assertions in order to make sure some rules & patterns are considered, which are totally different things. I wanted to know what examples can be given for the part solves a problem for us that we previously relied on ESLint for. Do these two things have anything in common? What are their similar purposes?

Answer

Because JavaScript is a dynamically typed language, programmers can more easily introduce subtle bugs and errors that fail at runtime compared to static languages with a compiler that picks up on common issues.

Take the following code for example:

console.log(someUndefinedVariable)

const constant = 0
constant = 3

const addOne = n => {
  if (typeof n !== 'nubmer') {
    throw new Error('n must be an number')
    console.log('This will never be executed')
  }
  if (n < 0) console.log('negative number')
  else return n + 1
}
console.log(addOne(-3) * 2)

const symbol = new Symbol()

This code will fail at runtime and also has some other issues that may lead to unexpected results.

Linters such as ESLint pick up on some of these issues with rules such as no-undef and no const-assign:

 1:13  error  'someUndefinedVariable' is not defined      no-undef
 4:1   error  'constant' is constant                      no-const-assign
 7:20  error  Invalid typeof comparison value             valid-typeof
 9:3   error  Unreachable code                            no-unreachable
16:20  error  `Symbol` cannot be called as a constructor  no-new-symbol

Similarly, TypeScript’s compiler will also warn you about many of these issues:

Cannot find name 'someUndefinedVariable'.

Cannot assign to 'constant' because it is a constant.

This condition will always return 'true' since the types
'"string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"'
and '"nubmer"' have no overlap.

Unreachable code detected.

'new' expression, whose target lacks a construct signature, implicitly has an 'any' type.

In this sense, ESLint and TypeScript have the same goal: to prevent likely programmer errors by warning you beforehand. For these issues, you can turn off the respective ESLint rules and use the TypeScript compiler instead.


However, the most important feature about TypeScript is its addition of static types to JavaScript. By adding type annotations to addOne:

const addOne = (n: number): number => { /* ... */ }

TS tells us that Function lacks ending return statement and return type does not include 'undefined'. because the function will return undefined instead of a number if n is a negative number. The result of addOne(-3) * 2 would be NaN, instead of -4 like expected.

Another example, which ESLint would be completely fine with but fails at runtime:

const foo = 0
const bar = foo()
//          ~~~
// This expression is not callable.
//   Type 'Number' has no call signatures.

These are some of the many issues that TypeScript can help identify due to its type system.

On the other hand, linters including ESLint and the typescript-eslint plugin can enforce best practices such as using strict equality operators and correctly handling promises. They can also enforce stylistic conventions such as indentation, requiring or forbidding semicolons, or consistent type assertion styles.


TypeScript and ESLint have the similar goal of preventing programmer bugs and errors. However, due to its type system, TypeScript can pick up on more runtime and programming errors, whereas ESLint can enforce stylistic conventions and best practices.

Categories
discuss

Will it cause error if I launch MediaRecorder.start() in suspend fun and launch MediaRecorder.stop() in normal fun in Android?

Recording audio is a long time operation, so I launch mRecorder?.start() in a coroutine within a service, you can see RecordService.kt.

I invoke suspend fun startRecord(){...} in AndroidViewModel with viewModelScope.launch { } to start record audio.

I only invoke a normal fun stopRecord(){...} in AndroidViewModel to stop record audio, you can see HomeViewModel.kt, will it cause error with the object var mRecorder: MediaRecorder? ?

HomeViewModel.kt

class HomeViewModel(val mApplication: Application, private val mDBVoiceRepository: DBVoiceRepository) : AndroidViewModel(mApplication) {

    private var mService: RecordService? = null

    private val serviceConnection = object : ServiceConnection {
        override fun onServiceConnected(className: ComponentName, iBinder: IBinder) {
            val binder = iBinder as RecordService.MyBinder
            mService = binder.service
        }
       ...
    }


    fun bindService() {
        Intent(mApplication , RecordService::class.java).also { intent ->
            mApplication.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE)
        }
    }  

    fun unbindService() {
        Intent(mApplication, RecordService::class.java).also { intent ->
            mApplication.unbindService(serviceConnection)
        }
    }

    fun startRecord(){
        viewModelScope.launch {
            mService?.startRecord()
        }
    }

    fun stopRecord(){
        mService?.stopRecord()
    }      
}

RecordService.kt

class RecordService : Service() {

    private var mRecorder: MediaRecorder? = null

    suspend fun startRecord(){

        mRecorder = MediaRecorder()

        withContext(Dispatchers.IO) {
            mRecorder?.setOutputFile(filename);

            mRecorder?.setMaxDuration(1000*60*20); //20 Mins
            mRecorder?.setAudioChannels(1);
            mRecorder?.setAudioSamplingRate(44100);
            mRecorder?.setAudioEncodingBitRate(192000);

            mRecorder?.prepare()
            mRecorder?.start()
        }
    }


    fun stopRecord(){
        mRecorder?.stop()
        mRecorder=null
    }

}

Answer

No, it doesn’t cause error but if you face runtime error while calling this method it may be caused by the recorder didn’t receive any valid sound or video to record. Check below documentation link for more information.

https://developer.android.com/reference/android/media/MediaRecorder#stop()

Categories
discuss

How to split HTML Page in A4 size in Angular 9

I am trying to create something like in Xing the CV maker -> https://lebenslauf.com/.

I do have different Arrays of Objects. But I am not able to create the A4 pages which will render the data and if the array it is larger than one page create new page A4 and add data there. The function needs to be so if the array is larger for one size, then create a new page a4 and put the data there. In the stackblitz I have added an array and some random text and designed an A4 letter. I referred to this question and answer, but didn’t help me too much. CSS to set A4 paper size.
I tried to fake pagination and to create A4 sizes but didn’t work.
I looked in this code with jquery there. It works, but I am unable to compile it in Angular. https://jsfiddle.net/tm637ysp/10/ Can someone help me here ?

I have created two projects in stackblitz. Maybe they will help.
https://stackblitz.com/edit/angular-ivy-fjhpdu.
https://stackblitz.com/edit/angular-ivy-uzmdwg

I wanted to reopen this question because the approved answer from @HirenParekh it doesn’t work as I wanted. The problem it is now, If the text in one Object it is very large it wont add a new page in a realtime, but only if I reload the page. I think that the code will be for add new page or edit page will be rendered only in ngOnInit. The directive that is provided to do that job, I think it is not working as excepted. Here is the stackblitz what he tried to help me. https://stackblitz.com/edit/angular-ivy-zjf8rv

This is the code I am trying 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>{{currentUser?.firstName}} {{currentUser?.lastName}}</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' | translate}}</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' | translate}}</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' | translate}}</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' | translate}}</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>

This is the CSS

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

 

This is the json

{
    "personalData": [
        {
  
            "firstName": "Max",
            "lastName": "Muster",
            "email": "max.musterman@outlook.com",
            "birthday": "2020-09-25T00:00:00.000Z",
            "telephone": "0123456789",
            "job": "Freelancer",
            "country": "Germany",
            "postalCode": 12345,
            "city": "None",
            "title": 2,
            "gender": 0,
            "street": "Musterman 12",
            "state": "",
            "status": 1,
            "showBirthday": true
        }
    ],
    "skills": [
        {
            "subCategories": [
                {
                    "languages": [
                        {
                            "name": "languages.de",
                            "rate": 5
                        },
                        {
                            "name": "languages.al",
                            "rate": 1
                        },
                        {
                            "name": "languages.en",
                            "rate": 5
                        },
                        {
                            "name": "languages.fr",
                            "rate": 4
                        },
                        {
                            "name": "languages.it",
                            "rate": 4
                        }
                    ],
                    "pcKnowledge": [
                        {
                            "_id": "5f5ca07e4dba443f786ea7ae",
                            "name": "Word"
                        },
                        {
                            "_id": "5f5ca07e4dba443f786ea7af",
                            "name": "Adobe Photoshop"
                        },
                        {
                            "_id": "5f5fd46bb21df2444c39f317",
                            "name": "Test"
                        },
                        {
                            "_id": "5f5fd46bb21df2444c39f318",
                            "name": "Excel"
                        },
                        {
                            "_id": "5f5fd46bb21df2444c39f319",
                            "name": "Ja"
                        },
                        {
                            "_id": "5f72339552009b4244391972",
                            "name": "Powerpoint"
                        }
                    ],
                    "skillsOffer": [
                        {
                            "_id": "5f4a4e2d718d33092df2c327",
                            "name": "Angular"
                        },
                        {
                            "_id": "5f4a4e2d718d33092df2c327",
                            "name": "Java"
                        },
                        {
                            "_id": "5f4a4e2d718d33092df2c327",
                            "name": "Typescript"
                        },
                        {
                            "_id": "5f4a4e2d718d33092df2c327",
                            "name": "html"
                        },
                        {
                            "name": "Javascript"
                        }
                    ],
                    "driveLicenses": [
                        {
                            "_id": "5f5ca07e4dba443f786ea7ac",
                            "name": "B"
                        },
                        {
                            "_id": "5f5ca07e4dba443f786ea7ad",
                            "name": "C"
                        },
                        {
                            "_id": "5f5f204faa5d0205180bd581",
                            "name": "B"
                        }
                    ],
                    "name": "",
                    "qualifications": ""
                }
            ]
        }
    ]
}

And this is the Paginated view class for adding new page and splitting pages

<!-- display: none style will any child that does not have #pageContent local variable defined -->
<div class="content-wrapper" #contentWrapper style="display: block">
</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 {

}

Answer

It is all about dividing the given content to fit into the give page size.

We can create a component that will handle the dividing functionality for us. here is a StackBlitz Demo.

And here is a brief explanation.

Use the ContentChildren decorator to observe the change in content. every time the content changes we will run the page creation logic.

import {
  AfterContentInit,
  AfterViewInit,
  Component,
  ContentChildren,
  ElementRef,
  Input,
  OnInit,
  QueryList,
  ViewChild
} from "@angular/core";

@Component({
  selector: "app-paginated-view",
  templateUrl: "paginated-view.component.html",
  styleUrls: ["paginated-view.component.scss"]
})
export class PaginatedViewComponent implements AfterViewInit {
  @Input() pageSize: "A3" | "A4" = "A4";

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

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

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

  constructor() {}

  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;
    });

    //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;
  }
}

We can use this component in an application like this.

<app-paginated-view [pageSize]="'A4'">
    <h1 #pageContent>Hello World!!</h1>
    <p #pageContent>This content will be displayed in an A4 size page</p>
</app-paginated-view>

We have to provide the template variable #pageContent so that we can select them using @ContentChildren in our PaginatedViewComponent.

Note that we are using native dom APIs here to change the dom structure. it will only move the dom node from one place to another so if you have any event listener added or have any property binding to the content children they will work as it is.

Edit: I have also updated your stackblitz https://stackblitz.com/edit/angular-ivy-zjf8rv

Source: stackoverflow
Text is available under the Creative Commons Attribution-ShareAlike License; additional terms may apply. By using this site, you agree to the Privacy Policy, and Copyright Policy. Content is available under CC BY-SA 3.0 unless otherwise noted. The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 © No Copyrights, All Questions are retrived from public domain..