0

By "token", I mean one of these things:

user authorisation widget

I'd like to bind a click event to the white cross icon that appears next to each Role. A Role is simply an entity (JS object) with a Name property.

To get from a Role, to a token, I have the following function:

var closeIcon = '&nbsp;<i class="fa fa-times-circle" aria-hidden="true" data-bind="click: removeRoleForSelectedUser(role)" id="remove-role-btn"></i>';
self.createRoleToken = function(roleName) {
  return roleName + ' ' + closeIcon;
};

The looping is happening here:

<div class="roles-wrapper" data-bind="foreach: $root.selectedUser().roles()">
  <div class="role-token" data-bind="html: $root.createRoleToken(name())"></div>
</div>

Even though I have the data-bind="click: removeRoleForSelectedUser(role)" on my HTML markup, it still doesn't trigger the event, so I'm guessing it isn't bound.

I went to Google for answers, and saw this. so I tried to do that binding on my role token (targeting the id property). I did the binding on user selection as seen here:

self.setCurrentUser = function (user) {
  const newRolesArray = self.roles().filter(function (role) {
    return !contains(user.roles(), role);
  });
  self.userAvailableRoles(newRolesArray);
  self.selectedUser(user);
  ko.applyBindings(self, document.getElementById("remove-role-btn"));
}

That didn't work. It threw the following error:

chrome console error

What am I missing?

halfer
  • 19,824
  • 17
  • 99
  • 186
J86
  • 14,345
  • 47
  • 130
  • 228
  • 1
    The `id` you use for the close button does not seem to be unique – GôTô Mar 31 '17 at 08:52
  • Good point, and a silly mistake on my mark, let me change that and see if that makes a difference – J86 Mar 31 '17 at 08:54
  • still no go, I changed from **id** to **class**, and [did this](http://stackoverflow.com/a/8668193/613605) to apply the bindings, and still the click isn't triggered. – J86 Mar 31 '17 at 09:01
  • Wait, you re-apply the bindings when you select a user? – GôTô Mar 31 '17 at 09:04
  • I thought I had to! Do I not need to? Let me try! – J86 Mar 31 '17 at 09:06
  • Is there a good reason for putting the html for the close icon in your javascript, and not just making it part of the template? – James Thorpe Mar 31 '17 at 09:06
  • @JamesThorpe erm I've not used templates in knockout before, I'm new to Knockout. Is it easy to do this as a template? – J86 Mar 31 '17 at 09:07

1 Answers1

1

Rather than having a complex function that returns markup with extra bindings in, you should instead make the close icon part of the general template:

<div class="roles-wrapper" data-bind="foreach: $root.selectedUser().roles()">
  <div class="role-token">
    <span data-bind="text: name"></span>
    <i class="fa fa-times-circle" aria-hidden="true" data-bind="click: $root.removeRoleForSelectedUser"></i>
  </div>
</div>

There should also be no need to repeatedly call applyBindings, so you should also at least remove that part. Without seeing more of the code surrounding your question, it's hard to say if the above is exactly right, but it should get you on the way.

James Thorpe
  • 31,411
  • 5
  • 72
  • 93
  • Thank you, now that I think about it, what I was doing before was very silly. You're right, this worked straight away! – J86 Mar 31 '17 at 09:17
  • 1
    @Ciwan Generally if you're using knockout, there shouldn't be any reason to touch the DOM or any markup directly - let it do the work :) – James Thorpe Mar 31 '17 at 09:18