Why isn't this predefined function working?

Why isn't this predefined function working?
0

#1

I’m having trouble with a function predefined in Materialize, though I think my problem has to do with basic JS literacy that I lack. I’ve been using their “chip” class, documented at http://materializecss.com/chips.html. In my Twitch project (http://codepen.io/AbdiViklas/pen/rrrQQd?editors=0010) I’ve added a search-and-add capability, and I’ve got it to the point that a user can search for and add new channels. I’ve got a little array, nameList, keeping track of them, and when a channel is added the updated nameList is written to localStorage. Now I just need to get channels out of nameList when they’re deleted.

One of the predefined features of Materialize’s .chip is that when you click the little “x”, which has .close, the chip disappears. This much works fine. Now to capture the ID of the deleted chip and remove it from nameList. Based on http://materializecss.com/chips.html#events, they’ve got a handy chips.delete function predefined for me. But their explanation–

  $('.chips').on('chip.delete', function(e, chip){
    // you have the deleted chip here
  });

–needs a little translation for me. I “have” the deleted chip? what code do I actually write in that middle line to do something with it? I would have imagined something involving chip.id, but that yields nothing. I tried console.log(chip) and it logs “undefined”.

I’m also a little unclear on their instructions for “jQuery initialization” of chips, and the distinction between .chips, plural, and .chip singular, so the problem may lie in my use of the chips or how I’m initializing them…?


#2

Do you have a link to your full code (preferably in CodePen)?


#3

Sorry, yes; at the moment it’s http://codepen.io/AbdiViklas/pen/rrrQQd?editors=0010


#4

Update: I made a very simplified version to troubleshoot: http://codepen.io/AbdiViklas/pen/jrVLoQ?editors=1011

And I came up with a workaround:

$("i").click(function() {
  console.log($(this).parent().parent()[0].id);
});

… from looking at the very large objects that $(this) returns. And it works here. Buuuut, forking the original project and pasting: http://codepen.io/AbdiViklas/pen/yaVPBJ?editors=0011 … it doesn’t (nothing is logged). Another point: in the simplified pen, I had to take .chips off of the containing div or the chip disappeared, and some predefined formatting (sort of an <hr>) replaced it. In the main project, having .chips on it didn’t prevent the chips from appearing, but it did bring in a little of that formatting. Removing the class didn’t improve performance.

Ohhhh oh oh hold the phone, moving the function helps. In http://codepen.io/AbdiViklas/pen/yaVPBJ?editors=0011 I moved the $("i").click line into the main buildList function–li 55, inside the function but outside the for loop that generates all the offline channels. Now clicking logs the ID of only the online channels. If I move it into the for loop, then clicking the offline channels does nothing, and clicking an online channel logs its ID a zillion times.

Sooo this is about scope? and callbacks? grr. I don’t have the brain to wrap around it right now. Or is it what you were just telling me about–here I am trying to use $.click() again, and maybe there’s an issue about the event?


#5

Ok, I’ve had a play with this and I think I’ve got the problem. Here’s my project, which started out as a fork of yours, but I deleted everything and started over: link.

The crux of the issue is that I think you’re expecting something out of Materialize’s chips that they aren’t meant to, and cannot, deliver. They aren’t able to dynamically generate arbitrary markup. Chips are supposed to be very small amounts of information rendered in a very simple bit of pre-defined markup. Taking a look at my example, you can see that although I start with a bunch of tags, I didn’t define a single one in the HTML. All that you define in the markup is a place for the chips to go (the class chips), and in JavaScript, you’ll pass data objects that include the data you want to render in the chips. The data object will include text, and optionally an image in the markup, but no more.

Now, open up the console, then try adding and deleting some tags (type in the field and press enter to add). The event handling works as expected. Chips will not do what you want, but there are other options. I really like using Handlebars.js for this sort of thing. With Handlebars, you can define a template in the HTML, and in JavaScript, pass data into that template to be rendered. It’s very simple to get started and I would highly recommend it for this project as it makes generating dynamic content much easier. Check out this video and the one after it in the playlist - they will give you an idea of how to use it, but if you want me to make up a working example in CodePen, I can do that as well.


#6

Thanks! Yes, I’m guilty of “abusing” Materialize often–using chips as “Hey, I like how they’re little, make the image the right size without me saying anything, and come with predefined shadow, margin, padding etc.” I’ll check out Handlebars.

Meanwhile, it occurred to me that I could get the function I wanted from scratch, pretty much the same as the one you showed me to add from search results. The little "X"s have a class of .close, so

$('#chipList').on('click', ".close", function(){
  nameList.splice(nameList.indexOf(this.id), 1);
  localStorage.nameList = nameList;
});

(I moved the ID from the entire chip to the .close div to avoid a bunch of .parents. The $.parent() trap…