7

I am using Ionic Framework and its grid system (similar to Bootstrap). However, I believe my question is more AngularJS than Ionic components.

I have the following:

 <ion-col *ngFor="let col of row.cols"></ion-col>

Note that I must set values for each col dynamically so in case col.size === 2 the above must be rendered as:

 <ion-col *ngFor="let col of row.cols" col-2></ion-col>

One way is to set all cols in advance and call *ngIfs on whichever size I want which seems like an overkill for something simpler. I have also tried to do this: <ion-col *ngFor="let col of row.cols" [attr.col-2]="col.size === 2"></ion-col> With zero luck.

Possible values could be from 1 to 12. Any help is much appreciated! Thanks.

4
  • could you share some sample data for cols Commented Sep 11, 2018 at 10:52
  • Which do you mean, AngularJS or Angular? Commented Sep 11, 2018 at 10:56
  • @user1027620 is it same thing to do <ion-col *ngFor="let col of row.cols" class="col-2"></ion-col> or not the same? Commented Sep 11, 2018 at 11:20
  • @user1027620 I just realized I didn't quite understand what col.size means. Could you please clarify it? Commented Sep 11, 2018 at 11:57

4 Answers 4

8
+100

You can add directive

import { Directive, ElementRef, Renderer, Input, OnInit } from '@angular/core';

@Directive({
  selector: '[dynamic-col]'
})

export class DynamicColDirective implements OnInit {
  @Input('dynamic-col') value: string;

  constructor(private el: ElementRef, private _renderer: Renderer) {}

  ngOnInit() {
    this._renderer.setElementAttribute(this.el.nativeElement, 'col-' + this.value, '');
  }
}

And then:

<ion-col *ngFor="let col of row.cols; let i = index" dynamic-col="{{i}}"></ion-col>

I hope this helps you.

Sign up to request clarification or add additional context in comments.

Comments

3

Have you considered using ng-container's? They could be perfect as they don't display in the DOM.

This will still create all of your ion-col's as if they were generated using your original code but allow you to add attributes to the root element of the loop.

<ng-container *ngFor="let col of row.cols">
    <ion-col col-{{col.col-size}}></ion-col>
</ng-container>

If you have the array below:

{
  "rows": {
    "cols": {
      {
        "col-size": "2"
      },
      {
        "col-size": "4"
      },
      {
        "col-size": "6"
      }
    }
  }
}

The HTML then output is like below:

<ion-col col-2></ion-col>
<ion-col col-4></ion-col>
<ion-col col-6></ion-col>

1 Comment

This seemed the most easy & neat solution, but it didn't work for me - and i tried also in few variation
2

You can do this in typescript and bind to the innerHtml attribute:

component.ts:

  rows = {
    cols: [
      { "size": "1" },
      { "size": "3" },
      { "size": "5" }
    ]
  }
  html: string = '';

  constructor(public navCtrl: NavController) {
    this.rows.cols.map((col) => {
      this.html += '<ion-col class="col" col-' + col.size + '></ion-col>'
    });
  }
  ...

component.html:

  <div [innerHTML]="html | safeHtml"></div>
  ...

using pipe to disable Angular’s built-in sanitization.

safeHtml.pipe.ts:

@Pipe({name: 'safeHtml'})
export class Safe {
  constructor(private sanitizer:DomSanitizer){}

  transform(value) {
    return this.sanitizer.bypassSecurityTrustHtml(value);
    // return this.sanitizer.bypassSecurityTrustStyle(value);
    // return this.sanitizer.bypassSecurityTrustXxx(style); - see DomSanitizer docs
  }
}

See also:

Comments

1

In your question, you asked for AngularJS solution, but in your code you demonstrated Angular example instead. I want to make sure you understand that they are very different from each other.


The following code is taken from the project of my chess game, using AngularJS:

HTML Template

<main class="container">
    <div>
        <button class="btn btn-primary center" ng-click="startGame()">Start Chess</button>
    </div>
    <div class="game-board center">
        <div class="game-board-row" ng-repeat="row in rows">
            <div class="game-board-grid" ng-repeat="col in cols" data-x="{{ col }}" data-y="{{ row }}" ng-click="click(this);">
                <div class="piece" data-text-color="{{ game.data.grids[row][col].value.group }}" data-bg-color="game.data.grids[row][col].occupied">{{ game.data.grids[row][col].value.text }}</div>
            </div>
        </div>
    </div>
</main>

JavaScript (AngularJS)

<script type="text/javascript">
    let app = angular.module('game', []);
    app.run(($rootScope) => {
        $rootScope.rows = ['0', '1', '2', '3'];
        $rootScope.cols = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'];
    });
</script>

If you are using Angular instead, change the code into the following style:

HTML Template

<main class="container">
    <div>
        <button class="btn btn-primary center" (click)="startGame()">Start Chess</button>
    </div>
    <div class="game-board center">
        <div class="game-board-row" *ngFor="row in rows">
            <div class="game-board-grid" *ngFor="col in cols" [data-x]="col" [data-y]="row" (click)="click(this);">
                <div class="piece" [data-text-color]="game.data.grids[row][col].value.group" [data-bg-color]="game.data.grids[row][col].occupied">{{ game.data.grids[row][col].value.text }}</div>
            </div>
        </div>
    </div>
</main>

JavaScript (Angular)

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-game',
  templateUrl: './game.component.html',
  styleUrls: ['./game.component.scss']
})
export class GameComponent implements OnInit {

  rows = ['0', '1', '2', '3'];
  cols = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'];

  constructor() { }

  ngOnInit() {
  }

}

When you want to select those grids with CSS, you need attribute selector! For example:

[data-x="1"][data-y="2"] {
    /* This selects the grid located at (1, 2) */
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.