Chirdeep Tomar
Chirdeep Tomar

Reputation: 4461

create a new HTML element inside directive and add click event

I am trying to create a faceting widget that works with Solr. How do I add ng-click event to each newly added facet item. So when a user clicks on an item in the list, I can re-query solr.

HTML Usage:

<facet field="query.response.facets.facet_fields.location" name="location" />

Directive:

var commonComponentsApp = commonComponentsApp || angular.module('cpUtils', []);
commonComponentsApp.directive("facet", function($compile) {
'use strict';
return {
    restrict: "E",
    scope: {
        field: "=",
        name: "@"
    },
    link: function (scope, element) {
        var list = new Array(), i, facet_item;
        scope.$watch('field', function (data) {
            if (data === undefined || data === null) {
                return;
            }
            for (i = 0; i <= data.length - 1 ; i += 2) {
                facet_item = '<li class="unstyled" ng-click=applyFilter('+ scope.name + "," + data[i] + ')>' + data[i] + " (" + data[i + 1] + ")</li>";
                var e = angular.element(facet_item);
                $compile(e.contents())(scope);
                list.push(e);
            }
            element.html(list);
        });

        scope.applyFilter = function (facet, value) {
            console.log("called");
            console.log(facet + ' ' + value);
        }
    }
};
});

Thanks

Upvotes: 0

Views: 886

Answers (1)

Charlie Martin
Charlie Martin

Reputation: 8406

I can see a few issues here. First, you are compiling the contents of your li item, instead of the element itself...

$compile(e.contents())(scope);

The ng-click directive is on the actual li element, so you need to compile the entire thing, instead of just its children. Change that line to...

e = $compile(e)(scope);

Next, you are $watching the value of scope.field, which appears to be an array, based upon your for loop. Therefore, you should use $watchCollection, instead of $watch.

scope.$watchCollection('field', ...

Next, you can't add a native javascript array to the DOM...

    ...
    list.push(e);
}
element.html(list);

Instead of adding each compiled element to an array, append each to the DOM immediately. So change the above to...

    ...
    element.append(e);
}

It will happen so fast it will appear that they are all added to the DOM at the same time.

Finally, assuming that the arguments you are passing to your ng-click function are strings, you need to put them in quotes. Change the line to something like this...

facet_item = '<li class="unstyled" ng-click=applyFilter("'+ scope.name + '","' + data[i] + '")>' + data[i] + ' (' + data[i + 1] + ')</li>';

Angular $evaluates the parameters in ng-click, meaning essentially it treats them like javascript code, which allows you to pass variables. If you don't have the quotes, it thinks that they are variables (which are undefined), when in your case they are actually just primitives (strings I assume)

Upvotes: 1

Related Questions