Using knockout.js, is there anyway to control the div attributes contained within a foreach

Here is my asp.net

 <div data-bind="foreach {data:movies}">
    <div class="content-item full bottom-border">
    <div class="content-item-container">
        <div class="movie-listing-header">
            <a class="icon arrow" data-bind="click: $parent.toggle"></a>

            <div class="movie-details">
                <div class="title"><a href="#" data-bind="text: MovieName, attr: { href: DetailsUrl }"></a></div> 
                <div class="info">
                    <div class="rating">
                    </div>
                    <div class="time" data-bind=" text: movieruntime "></div>
                </div>
            </div>
            <a class="icon right-arrow" href="#" data-bind="attr: { href: DetailsUrl }"></a>
        </div>         
        <div class="showtimes">    
           <div data-bind="template: { name: 'movie-grouped-showtimes-template', data: $data }"></div>
        </div>
     </div>
     </div>
</div>

What I would like to be able to do is simply, click on <a class"arrow icon"> and be able to toggle the following:

<div class="movie-listing-header"> -- addClass(.active); <div class="showtimes"> -- style: block;

I can get the showtimes to work, but it adds the styling to each movie, and I want to control the toggle contained with the movie.

here is the .js

 function TheatreViewModel(theatre) {
        var self = this,
            initialData = theatre || Regal.userPrimaryTheatre || {},
            theatreServiceParams = {
                tmsId: initialData.TmsId,
                date: initialData.selectedDate || new Date()
            };

        self.TheatreName = initialData.TheatreName || '';
        self.PhoneNumber = initialData.PhoneNumber || '';
        self.selectedTheatreTms = initialData.TmsId;
        self.theatre = ko.observable();
        self.isLoading = ko.observable(false);
        self.selectedDate = ko.observable(initialData.selectedDate || new Date());

        self.filterFormats = [];

        self.selectedFormat = ko.observable(Regal.allFormatsFilterItem);
        self.filterFormats.push(Regal.allFormatsFilterItem);
        if (Regal.movieFormats) {
            var filtered = _.where(Regal.movieFormats, {
                Filterable: true
            });
            _.forEach(filtered, function(f) {
                f.enabled = ko.observable(false);
                self.filterFormats.push(f);
            });
        }

        self.addressText = ko.computed(function() {
            var theat = ko.unwrap(self.theatre);
            var addie;
            if (!theat || theat && !theat.Address1) {
                addie = initialData;
            } else {
                addie = theat;
            }

            return addie.Address1 + ', ' + addie.City + ' ' + addie.State + ' ' + addie.PostalCode;
        });

        self.mapEmbedUrl = ko.computed(function() {
            var a = self.addressText();
            return 'http://maps.google.com/maps?q=' + encodeURI(a);
        });

        self.movies = ko.computed(function() {
            var thea = self.theatre(),
                mov = ko.unwrap((thea || {}).Movies),
                format = self.selectedFormat();

            if (format && format !== Regal.allFormatsFilterItem) {
                return _.filter(mov, function(m) {
                    return _.contains(_.pluck(m.formats(), 'Id'), format.Id);
                });
            }
            return mov;
        });

        self.getPerformances = function() {
            self.isLoading(true);
            Regal.loadTheatre(self.selectedDate(), self.selectedTheatreTms,
                function(data) {
                    self.isLoading(false);
                    if (data) {

                        var allFmts = _.uniq(_.flatten(_.map(ko.unwrap(data.Movies), function(mov) {
                            return mov.formats();
                        })));
                        _.forEach(allFmts, function(fmt) {
                            var filt = _.findWhere(self.filterFormats, {
                                Id: fmt.Id
                            });
                            if (filt) {
                                filt.enabled(true);
                            }
                        });
                        self.theatre(data);
                    }

                });
        };
        self.changeFormat = function(format) {
            console.log(format);
            self.selectedFormat(format);
            self.movies();

        };


        self.selectedDate.subscribe(function(newVal) {
            self.getPerformances();
        });


        self.getPerformances();






   self.toggle = function () {

        $('.showtimes').show();
        $('.movie-listing-header').addClass('.active');


}
    }

    window.Regal.TheatreViewModel = TheatreViewModel;

any help would be appreciated, I can't believe that this cannot be accomplished.

note: before I added knockout ... here is the jquery that was in place and working ...

$(document).ready(function () {
    $('.icon.arrow').click(function () {
        var active_el = $(this);
        $('.movie-listing-header').each(function () {
            if ($(this).get(0) === active_el.parent().get(0)) {

                if ($(this).hasClass('active')) {
                    $(this).siblings('.showtimes').hide();
                } else {
                    $(this).siblings('.showtimes').show();
                }
                $(this).toggleClass('active');

            } else {
                $(this).removeClass('active');
                $(this).siblings('.showtimes').hide();
            }
        });

    });
});

Answers


You could use a custom binding handler here but a more generic way of doing it would be as such -

Use the css and style bindings to toggle the classes -

<div data-bind="foreach: computedMovies">
    <div class="movie-listing-header" data-bind="css: { 'active' : isActive() }, click: toggleClass">
        <div class="showtimes" data-bind="style: { 'display': isSelected() ? 'block' : 'none' }">
        </div>
    </div>
</div>

And in your view model, create a computed to add some additional properties -

var computedMovies = ko.computed(function() {
    var theseMovies = [];
    ko.utils.arrayForEach(movies(), function (movie) {
        movie.isActive = ko.observable(false);
        movie.isSelected = ko.observable(false);
        theseMovies.push(movie);
    });
    return movies;
});
function toggleClass() {
    isActive(!isActive());
}

Edited with jsFiddle

http://jsfiddle.net/gNE77/


Need Your Help

How to read binary-protobuf gz files in Spark / Spark Streaming?

apache-spark gzip protocol-buffers

I have to read the gz file from local / hdfs / kafka, and decompress it and parse it. Who have any experiences about this?