基于字符串过滤knockout observable数组

Filtering knockout observable array based on string

我目前正在尝试解决一个小问题。

我有以下代码。我尝试根据所选类型过滤并重新渲染获取的电影列表。

到目前为止,我可以将 selected 选项投射到我的 js 脚本中的一个对象,但我不知道从这里可以去哪里。我的可观察数组中的类型值是它自己的数组,因为一部电影可以有多种类型。

到目前为止,这是我的脚本:

define(['knockout', 'dataservice'], (ko, dataservice) => {
return function () {
    let movies = ko.observableArray([]);
    let movieList = ko.observableArray([])
    let genres = ko.observableArray([]);
    let pageSizes = ko.observableArray();
    let prev = ko.observableArray();
    let next = ko.observableArray();
    let selectedPage = ko.observableArray([10]);
    self.selectedGenre = ko.observable();
    let objGenre = ko.observable();
    let movieGenres = ko.observable();

    self.selectedGenre.subscribe(() => {
        objGenre = selectedGenre().name;
        console.log(objGenre)
        });   

    console.log(chosenGenre)

    self.getMovies = function () {
        ko.mapping.fromJS(data.movies, {}, self.movies)
    }

    let getMovies = url => {
        dataservice.getMovies(url, data => {
            pageSizes(data.pageSizes);
            prev(data.prev || undefined);
            next(data.next || undefined);
            movieList(data.movieList);
            movieGenres(movieList.genre)
        });
    }
   
    let getGenres = function () {
        fetch('http://localhost:5001/api/genre')
            .then(function (response) {
                return response.json();
            })
            .then(function (data) {
                genres(data);

                console.log(genres());
            })
    };


    // INDSÆT GAMMEL FETCH

    let showPrev = movie => {
        console.log(prev());
        getMovies(prev());
    }

    let enablePrev = ko.computed(() => prev() !== undefined);

    let showNext = product => {
        console.log(next());
        getMovies(next());
    }

    let enableNext = ko.computed(() => next() !== undefined);

    selectedPage.subscribe(() => {
        var size = selectedPage()[0];
        getMovies(dataservice.getMoviesUrlWithPageSize(size));
    });


    document.getElementById("scrolltotop").addEventListener("click", function () {
        console.log("Clicked!");
        $('html,body').animate({scrollTop: $('#scrolltothisdiv').offset().top}, 1000);
    });

    document.getElementById("prevscrolltotop").addEventListener("click", function () {
        console.log("Clicked!");
        $('html,body').animate({scrollTop: $('#scrolltothisdiv').offset().top}, 1000);
    });

    getMovies();
    getGenres();

    self.optionsAfterRender = function (option, view) {
        if (view.defaultView) {
            option.className = 'defaultViewHighlight';
        }
    };


    return {
        pageSizes,
        selectedPage,
        movies,
        movieList,
        showPrev,
        enablePrev,
        showNext,
        enableNext,
        genres,
        optionsAfterRender,
        selectedGenre
    };
}

});

Dataservice脚本绑定require js和postman中获取的数据+html

    <section class="after-head d-flex section-text-white position-relative">
    <div class="top-block top-inner container">
        <div class="top-block-content">
            <h1 class="section-title">Movies</h1>
            <div class="page-breadcrumbs">
                <a class="content-link" href="#">Home</a>
                <span class="text-theme mx-2"><i class="fas fa-chevron-right"></i></span>
                <span>Movies</span>
            </div>
        </div>
    </div>

</section>
<a id="topOfPage"></a>
<a id="top"></a>
<section class="section-long">   <!-- GENRES CONFIG HERE-->
    <div class="container">
        <div class="section-pannel">
            <div class="grid row">
                <div class="col-md-10">
                    <form autocomplete="off">
                        <div class="row form-grid">
                            <div class="col-sm-6 col-lg-3">
                                <div id="scrolltothisdiv"></div>
                                <div class="input-view-flat input-group">
                                    <select class="form-control" data-bind=
                                            "options: genres,
                                             optionsText: 'name',
                                             value: selectedGenre
                                          ">
                                    </select>
                                </div>
                            </div>
                            <div class="col-sm-6 col-lg-3">  <!-- START YEAR AND END YEAR HERE -->
                                <div class="input-view-flat date input-group" data-toggle="datetimepicker"
                                     data-target="#release-year-field">
                                    <input class="datetimepicker-input form-control" id="release-year-field"
                                           name="releaseYear" type="text" placeholder="release year"
                                           data-target="#release-year-field" data-date-format="Y"/>
                                    <div class="input-group-append">
                                        <span class="input-group-text"><i class="fas fa-calendar-alt"></i></span>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>

        <!-- WRAP DEN HER IN I KNOCKOUT ARRAY -->
        <table>

            <tbody>  <!-- FOR HVER FETCHED -->
            <tr>

                <td data-bind="foreach: movieList">
                    <article class="movie-line-entity"> <!-- HVER ARTICLE I TABLE HER CONFIG-->
                        <div class="entity-poster" data-role="hover-wrap"> <!-- HOVER OVER BILLEDER -->
                            <div class="embed-responsive embed-responsive-poster">
                                <img class="embed-responsive-item" data-bind="attr:{src: poster}" alt=""/>
                                <!-- BILLEDE SRC HER -->
                            </div>
                            <div class="d-over bg-theme-lighted collapse animated faster"
                                 data-show-class="fadeIn show" data-hide-class="fadeOut show">
                                <div class="entity-play">  <!-- NEDENSTÅENDE ER LOGO -->
                                    <svg width="1em" height="1em" viewBox="0 0 16 16"
                                         class="bi bi-box-arrow-up-right" fill="currentColor"
                                         xmlns="http://www.w3.org/2000/svg">
                                        <path fill-rule="evenodd"
                                              d="M8.636 3.5a.5.5 0 0 0-.5-.5H1.5A1.5 1.5 0 0 0 0 4.5v10A1.5 1.5 0 0 0 1.5 16h10a1.5 1.5 0 0 0 1.5-1.5V7.864a.5.5 0 0 0-1 0V14.5a.5.5 0 0 1-.5.5h-10a.5.5 0 0 1-.5-.5v-10a.5.5 0 0 1 .5-.5h6.636a.5.5 0 0 0 .5-.5z"/>
                                        <path fill-rule="evenodd"
                                              d="M16 .5a.5.5 0 0 0-.5-.5h-5a.5.5 0 0 0 0 1h3.793L6.146 9.146a.5.5 0 1 0 .708.708L15 1.707V5.5a.5.5 0 0 0 1 0v-5z"/>
                                    </svg>
                                </div>
                            </div>
                        </div>
                        <div class="entity-content">
                            <h4 class="entity-title">
                                <a class="content-link" href="movie-info-sidebar-right.html"><span
                                        data-bind="text: title_name"></span></a>
                            </h4>
                            <div data-bind="foreach: genre">
                                <div class="entity-category">
                                    <a class="content-link" href="movies-blocks.html"><span
                                            data-bind="text: $data"></span></a>,
                                </div>
                            </div>
                            <div class="entity-info">
                                <div class="info-lines"> <!--  RATING -->
                                    <div class="info info-short">
                                        <span class="text-theme info-icon"><i class="fas fa-star"></i></span>
                                        <span class="info-text"><span data-bind="text: rating"></span></span>
                                        <span class="info-rest">/10</span>
                                    </div>
                                    <div class="info info-short"> <!-- RUNTIME -->
                                        <span class="text-theme info-icon"><i class="fas fa-clock"></i></span>
                                        <span class="info-text"><span data-bind="text: runtime"></span></span>
                                        <span class="info-rest">&nbsp;<span>min</span></span>
                                    </div>
                                </div>
                            </div>
                            <p class="text-short entity-text">
                                <span data-bind="text: plot"></span>
                            </p>
                        </div>
                    </article>
                </td>
            </tr>
            </tbody>
        </table>


        <div class="section-bottom"> <!-- PAGING CONFIG HER -->
            <div class="paginator">
                <div class="navigation-buttons">
                    <button id="prevscrolltotop" onclick="scrolltotop" type="button"  class="btn btn-inverse btn-warning" data-bind="click: showPrev, enable: enablePrev" href="#"> Prev</button>
                    <button id="scrolltotop" onclick="scrolltotop" type="button" class="btn btn-warning btn-rounded" data-bind="click: showNext, enable: enableNext" href="#">Next</button>
                </div>
            </div>
        </div>

      
    </div>
</section>

获取邮递员[=3​​7=]

{
"pageSizes": [
    5,
    10,
    15,
    20
],
"count": 55076,
"pages": 2754,
"prev": null,
"next": "http://localhost:5001/api/title?page=1&pageSize=20",
"movieList": [
    {
        "title_id": "tt0052520",
        "title_name": "The Twilight Zone",
        "poster": "https://m.media-amazon.com/images/M/MV5BNTAzMDI5MzgtMGNkMC00MzllLWJhNjctNjA1NmViNGUxMzYxXkEyXkFqcGdeQXVyMTQxNzMzNDI@._V1_SX300.jpg",
        "plot": "Ordinary people find themselves in extraordinarily astounding situations, which they each try to solve in a remarkable manner.",
        "runtime": "51",
        "genre": [
            "Fantasy",
            "Horror",
            "Drama"
        ],
        "votes": "68643",
        "rating": "9.0",
        "type": "tvSeries",
        "url": "http://localhost:5001/api/title/tt0052520"
    },
    {
        "title_id": "tt0063929",
        "title_name": "Monty Python's Flying Circus",
        "poster": "https://m.media-amazon.com/images/M/MV5BMWY2ZGI0OGUtZDc3YS00ZmVjLWJiNWQtZDdmNzFmM2UzYWFhXkEyXkFqcGdeQXVyNTA4NzY1MzY@._V1_SX300.jpg",
        "plot": "The irreverent Monty Python comedy troupe present a series of skits which are often surreal, bawdy, uncompromising and/or tasteless, but nearly always hilarious.",
        "runtime": "30",
        "genre": [
            "Comedy"
        ],
        "votes": "65618",
        "rating": "8.8",
        "type": "tvSeries",
        "url": "http://localhost:5001/api/title/tt0063929"
    },
    {
        "title_id": "tt0078672",
        "title_name": "Pride and Prejudice",
        "poster": "https://m.media-amazon.com/images/M/MV5BMjA5MTg2OTYyN15BMl5BanBnXkFtZTcwMzAwODUyMQ@@._V1_SX300.jpg",
        "plot": "Mrs. Bennet is determined to find husbands for her five daughters. The arrival of a new wealthy neighbor seems like the answer to her predicament. But while eldest daughter Jane catches Mr. Bingley''s eye, middle child Mary has her nose stuck in a book, and youngest girls, Kitty and Lydia, chase after officers in uniform; Elizabeth, the willful, intelligent, and opinionated second daughter, is snubbed by haughty gentleman Mr. Darcy... In this class-minded society, can love triumph over pride and prejudice?",
        "runtime": "265",
        "genre": [
            "Romance",
            "Comedy",
            "Drama"
        ],
        "votes": "2128",
        "rating": "7.3",
        "type": "tvMiniSeries",
        "url": "http://localhost:5001/api/title/tt0078672"
    },
    {
        "title_id": "tt0088634",
        "title_name": "The Twilight Zone",
        "poster": "https://m.media-amazon.com/images/M/MV5BOTc4YjU0ZDktNzE2Ny00MDdmLWIwZDQtMzU2NzhmODA4YmMwXkEyXkFqcGdeQXVyNjExODE1MDc@._V1_SX300.jpg",
        "plot": "An updated version of the famous 1960''s TV series created by Rod Serling. Each week presents one to three tales about some unusual situation that turns out to be even more unusual than initially suspected. Whether the tone of the story is horror, suspense or humor, there is always a surprise twist at the end.",
        "runtime": "45",
        "genre": [
            "Fantasy",
            "Horror",
            "Drama"
        ],
        "votes": "9822",
        "rating": "7.8",
        "type": "tvSeries",
        "url": "http://localhost:5001/api/title/tt0088634"
    },
    {
        "title_id": "tt0098286",
        "title_name": "Good News, Bad News",
        "poster": "N/A",
        "plot": "In this episode, the predecessor to Seinfeld (1989), Jerry is expecting a woman that he met in Michigan to come and visit him in New York. Throughout the first part of the show Jerry and George are discussing the situation. Later we meet \"Kessler\" who comes in to Jerry''s apartment to borrow some meat and uncharacteristically knocks on the door before entering.",
        "runtime": "23",
        "genre": [
            "Comedy"
        ],
        "votes": "3501",
        "rating": "7.6",
        "type": "tvEpisode",
        "url": "http://localhost:5001/api/title/tt0098286"
    },
    {
        "title_id": "tt0098769",
        "title_name": "The Civil War",
        "poster": "https://m.media-amazon.com/images/M/MV5BZDc1NzI2MGEtZDA2Yy00ZWExLTgwYmItNjU3N2QyYmM0MzYwXkEyXkFqcGdeQXVyNTA4NzY1MzY@._V1_SX300.jpg",
        "plot": "This highly acclaimed mini series traces the course of the U.S. Civil War from the abolitionist movement through all the major battles to the death of President Lincoln and the beginnings of Reconstruction. The story is mostly told in the words of the participants themselves, through their diaries, letters, and Visuals are usually still photographs and illustrations of the time, and the soundtrack is likewise made up of war-era tunes played on period instruments. Several modern-day historians offer periodic comment and insight on the war''s causes and events.",
        "runtime": "680",
        "genre": [
            "History",
            "War",
            "Documentary"
        ],
        "votes": "13075",
        "rating": "9.0",
        "type": "tvMiniSeries",
        "url": "http://localhost:5001/api/title/tt0098769"
    }

数据服务

define([], () => {
const movieApiUrl = "api/title";
const genreApiUrl = "api/genre";


let getJson = (url, callback) => {
    fetch(url).then(response => response.json()).then(callback);
};

let getMovies = (url, callback) => {
    if (url === undefined) {
        url = movieApiUrl;
    }
    getJson(url, callback);
};

let getGenres = (url, callback) => {
    if(url === undefined) {
        url = genreApiUrl;
    }
    getJson(url, callback)
};

let getMoviesUrlWithPageSize = size => movieApiUrl + "?pageSize=" + size;


return {
    getMovies,
    getMovie: getJson,
    getMoviesUrlWithPageSize,
    getGenres
};

我想实现这样的目标,但是从我的 select 标签中的下拉列表中:

https://jsfiddle.net/jchaplin2/9o4utk6t/1/

您可以添加一个计算的可观察对象 filteredMoviesList,它将通过您描述的每个过滤器并针对所选类型进行过滤。然后在您的 html 中,您只需将您的 foreach 绑定绑定到它而不是 moviesList。这是一个简单的例子:

JS

let filteredMovieList = ko.computed(() => {
    let tempList = ko.toJS(movieList);
    if (this.selectedGenre()) {
        tempList = tempList.filter(movie => movie.genre == this.selectedGenre().name);
    }
    return tempList;
});

HTML

<div data-bind="foreach: filteredMovieList">
    <span data-bind="text: title + genre"></span>
</div>

您必须对其进行编辑以匹配您的用例,但过去类似的解决方案对我有用。祝你好运!