Utilizing Knockout bindings to incorporate FontAwesome icons

View the code snippet here

Hey there,

I'm currently facing an issue with binding a CSS class from font-awesome to an <i> tag.

Here's a snippet of the HTML:

<div class="flex-no-shrink">
    <div class="btn-group">
        <div data-bind="foreach: toolbarButtons">
            <button type="button" class="btn btn-xs btn-primary" data-bind="enable: enabled, visible: visible, click: onClick">
               <i class="fa" data-bind="css: { class: icon }"></i>
                <!-- <i class="fa fa-plus"></i> -->
            </button>
              <button type="button" class="btn btn-xs btn-primary" data-bind="enable: enabled, visible: visible, click: onClick">
                 <i class="fa fa-plus"></i>
            </button>
        </div>
    </div>
</div>

In the TypeScript:

interface IToolbarButton {
enabled: KnockoutComputed<boolean>;
visible: KnockoutComputed<boolean>;
icon: string;
onClick();
}

export abstract class ViewModel {
toolbarButtons: IToolbarButton[];

constructor(){
this.loadDefaultToolbar();
}
loadDefaultToolbar(): void {
    this.toolbarButtons = [];
    //add button
    this.toolbarButtons.push({
        enabled: knockout.pureComputed(() => true/*some internal logic*/),
        icon: 'fa fa-plus',//This is where I want to insert the icon into the <i> tag
        onClick: () => {/*some internal logic*/},
        visible: knockout.pureComputed(() => true/*some internal logic*/)
    });
    //Add more default buttons...
    }
};

ko.applyBindings(new ViewModel());

What would be the correct way to bind it in my case?

Check out the code example

I've already tried basic bindings like text or simply css: { icon } but they didn't work. Any guidance would be greatly appreciated!

Thanks for taking the time to help 🙂

Answer â„–1

The css binding comes in two different forms:

  1. The first form accepts an object with classes as property names and values as boolean expressions:

    css: {className: booleanExpression}
    

    ...where the className is added if the booleanExpression is true (it will be left out if false).

  2. The second form allows you to specify the class name(s) to include as a string:

    css: stringExpression
    

It seems like you have attempted to mix both syntaxes together; what you really want is the second one. Unlike using the attr binding incorrectly, this method respects other classes that are already applied to the element. This functionality of the css binding is explained here and can be found in the source code here.

Take a look at the Live Example section below to see it in action:

ko.applyBindings({
  someClassName: "two",
})
.one { background: yellow; }
.two { color: red; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<div class="one" data-bind="css: someClassName">
  My text is red because the view model added a class name!
</div>

If you would like to explore more examples or compare them, feel free to leave a comment.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Could a variable (not an element) be defined and controlled within an Angular 2 template?

For instance, envision a scenario where I have a series of input fields and I wish to assign the 'tab' attribute to them sequentially as we move down the page. Rather than hard-coding the tab numbers, I prefer to utilize a method that automatical ...

Unable to utilize createRoot function in TypeScript: "TypeError: m.createRoot is not a function"

Currently, I am working on a React 18 project that involves Leaflet. While I don't suspect Leaflet is causing the issue, it's worth noting. My challenge lies in adding custom elements to the map, as utilizing createRoot results in a TypeError: m. ...

Ways to verify the functionality of a function utilizing a Subscription that yields no return value

I'm working with a TypeScript ModelService that has an edit function: edit(model: Model): Observable<Model> { const body = JSON.stringify(model); return this.http.put(`/models/edit/${model.id}`, body)); } Additionally, there is a TypeScrip ...

Translating Python's slicing assignment syntax to JavaScript/TypeScript: A guide

Currently, I am in the process of converting a Python library into TypeScript. One specific challenge I am facing is translating this line of code from this particular repository: is_prime[start - segment_min::pk] = repeat(False, len(range(start - segment ...

Steps for transitioning from a mapped type to a discriminated union

Forgive me if this question has already been posed. I made an effort to search for a solution, but it seems I may not be using the correct terms. The issue arises with this particular structure. It involves a simple mapped type: type Mapped = { squ ...

Steps to activate zone-conscious bluebird assurances in Angular 8

In order to make all the promises in my Angular 8 project cancelable, I embarked on a quest to find the perfect library for the job. It was during this search that I stumbled upon bluebird.js, a promising candidate ;-) Following these guidelines on integr ...

To pass an interface property as an argument to another functional component

How do I reference an interface property as a parameter value in another functional component? interface InterfaceProperties { interfaceProperty1Id: number, interfaceProperty1Name : string } const tabsInterfaces: Map<InterfaceDetailEnum, JSX.Elemen ...

What is the best way to determine if a value from my array is present within a different object?

I have an array with oid and name data that I need to compare against an object to see if the oid value exists within it. Here is the array: const values = [ { "oid": "nbfwm6zz3d3s00", "name": "" ...

The third-party SDK no longer includes names and autocomplete functionality

I am encountering an issue where my previously working SDK environment has suddenly stopped recognizing names and providing autocomplete. I am wondering what could have caused this problem - is it related to SDK maintenance or is the SDK offline? The SDK ...

What exactly is a NativeScript app: is it the experience users have on their mobile devices, or the product they download from the app store?

Currently, I am diving into the world of Angular and exploring how to develop Angular applications with TypeScript while working on a C# ASP.Net Core Web Api project as the server side component. My question is this - if I create a NativeScript app in add ...

Correcting Typing Errors in TypeScript

My current challenge involves a method that is consuming data from an external API: public async getStatus(id: string): Promise<APIRes | undefined> { try { const result = await getRequest(`${this.URL}/endpoint/${id}`) const respo ...

Using optional chaining on the left side in JavaScript is a convenient feature

Can the optional chaining operator be used on the left side of an assignment (=) in JavaScript? const building = {} building?.floor?.apartment?.number = 3; // Is this functionality supported? ...

Bidirectional data binding in Angular 9 form controls

Implementing two-way binding in an Angular 9 form I attempted to use [(ngmodel)] in the form, however it resulted in an error. This feature has been deprecated in Angular 6 and newer versions. ...

React/TypeScript - react-grid-layout: The onDrag event is fired upon clicking the <div> element

I am currently working on creating a grid with clickable and draggable items using the react-layout-grid component. However, I am facing an issue where the drag is instantly activated when I click on the item without actually moving the cursor. Is there a ...

typescript add an html element to an existing html document

I'm experimenting with creating a dynamic HTML element using TypeScript to display on a webpage. In my .ts file, my code looks like this: const displayContent = document.getElementById("display-content") as HTMLOutputElement; var displayVariable = " ...

Obtain characteristics of the primary element in Ionic version 2 or 3

After creating and opening my Sqlite database and saving the SQLiteObject in a variable within my app.component.ts, I now need to retrieve these attributes in my custom ORM. The ORM extends to other providers to describe the title and field of my tables. ...

Implementing computed properties: A guide to incorporating type setting

I currently have two separate interfaces defined for Person and Dog. interface Person { name: string; weight: number; } interface Dog { name: string; mass: number } const specificAttribute = isDog ? 'mass' : 'weight'; ...

Initiate a POST request to the RESTful API using an Angular single-page application

I am working with a .Net Core Api integrated with an Angular SPA. I need to make a POST request to the REST API from the Angular SPA without displaying any components - just calling an http request. Can someone provide guidance on how to achieve this tas ...

The softAssert method is not available when trying to implement soft assertions within a TypeScript-based Protractor framework

Uncaught TypeError: assertion.softAssert is not a function I recently included a package called soft-assert using npm in my project. To install this package, I executed the following command: npm i soft-assert -g --save-dev Incorporated the following co ...

Navigating Transactions with Sequelize in NestJS

I have successfully incorporated sequelize ORM into my Typescript project. The database connection is working and queries are running smoothly. However, I am now facing difficulties in implementing transactions in my NestJS application as there seems to be ...