ionic-team / ionicons

Premium hand-crafted icons built by Ionic, for Ionic apps and web apps everywhere 🌎
http://ionicons.com
MIT License
17.39k stars 2.06k forks source link

Dynamically pass in icons imported from another component into a child addIcons function #1358

Closed francis-Paul-code closed 1 month ago

francis-Paul-code commented 1 month ago

originaly from Hello @liamdebeasi I see this issue was closed but it seems to be the closest to the problem I'm having. I'm fairly new to the Angular environment though have been using Ionic with react for a few years now.

Implementation Description Im trying to achieve somewhat what @tanishqmanuja was trying to achieve but in a different way and I think it should work. I've created a input component that is meant to be reusable throughout the project, It takes in an icon from the consumer and passes it into the addIcons()function for it to be bundled with the component.

// input field component
@Component({
  selector: 'app-input-field',
  template: '
  <ion-icon [name]="_icon!" ></ion-icon>
',
  styleUrls: ['./input-field.component.scss'],
})
export class InputFieldComponent implements OnInit {
  @Input() hasIcon!: boolean;
  @Input() icon?: { [name: string]: string };
  private _icon!: string;

  constructor() {
    this.hasIcon && addIcons(this.icon!);
  }

  ngOnInit() {
    if (this.hasIcon) {
      this._icon = Object.keys(this.icon!)[0];
    }
  }
}

//consumer component

import { add } from 'ionicons/icons';
@Component({
  selector: 'app-login',
  template: '
 <app-input-field [icon]="icon" [hasIcon]="hasIcon" ></app-input-field>
',
  styleUrls: ['./login.page.scss'],
})
export class LoginPage implements OnInit {
  hasIcon = true;
  icon = { ['add']: add };

  constructor() {}

  ngOnInit() {}
}

Use Case The field is meant to be reused throught the app with different icons so the exact icon needed needs to be passed by the consumer.

Problem On the component size the icon is recieved in the required format for addIcons, however the icon does not render, the ion-icon element renders with an empty native. This implementation is easily achievable in react, however in angular it seems impossible. Any idea why this doesnt work and any suggestion for a better implementation if this one is not achievable

Originally posted by @francis-Paul-code in https://github.com/ionic-team/ionicons/issues/1294#issuecomment-2026251897

liamdebeasi commented 1 month ago

Can you provide a runnable sample? It's hard to say what the issue could be from code snippets.

francis-Paul-code commented 1 month ago

Can you provide a runnable sample? It's hard to say what the issue could be from code snippets.

Let me create a codesandbox

francis-Paul-code commented 1 month ago

Hello @liamdebeasi I created a sample however, in that sample the implementation worked, so I tried to look for a reason why it wasn't working in my main app and came to the conclusion that possibly the reason is the complexity of the project I'm currently building. In my case my ionic angular project has nested projects inside of it App file structure

root 
      |___components
             |____input-field component (component utilizing the Ion-Icons)
      |___ auth app
             |____pages
                     |___logIn (consuming the inputfield component and passing in the required icon)
                     |___signUp (consuming the inputfield component and passing in the required icon)
      |___ admin dash
      |___main

the svg string from the import in the consumer component was reaching the inputfield component however for some reason it was not loaded into addIcons and not bundled, I've attached a warning from IonIcons. Screenshot from 2024-03-30 13-50-13

Solution Since the svg data was successfuly passing through instead of using addIcons to refer to the icon be name in the template, I switched to passing the svg data directly into the template.

// input field component
@Component({
  selector: 'app-input-field',
  template: '
  <ion-icon [icon]="_icon!" ></ion-icon>
',
  styleUrls: ['./input-field.component.scss'],
})
export class InputFieldComponent implements OnInit {
...
  ngOnInit() {
    if (this.hasIcon) {
      this._icon = this.icon!?.[Object.keys(this.icon!)[0]];
    }
  }
}

This solved it for me.

Conclusion I still don't know for sure why the addIcons didn't load the icon given the icon data was successfully passed, maybe @liamdebeasi could weigh in on that.

liamdebeasi commented 1 month ago

That warning usually means the icon was not being registered correctly before. If the bug only reproduces in your application then it's possible that something related to your application is contributing to this issue. I'd recommend trying to isolate the issue by removing parts of your code that are not needed to reproduce the issue.

You might want to try registering your icons in app.component.ts (or main.ts depending on use case). This will ensure that icons are registered regardless of the view you land on.

ionitron-bot[bot] commented 1 month ago

Thanks for the issue! This issue is being closed due to the lack of a reply. If this is still an issue with the latest version of Ionicons, please create a new issue and ensure the template is fully filled out.

Thank you for using Ionicons!