pythonhtmlvuejs2

How do i create a watch later feature to add movies to a section then remove later (No javascript allowed)(Use Vue2, HTML, and python)


For my assignment, I need to create a feature where people can add different movies to a watch later section. For this, we are only allowed to use Brython, HTML, CSS, and Vue(I believe our lecturer wants us to use Vue2) (no JavaScript is allowed). I have created some code where I think I'm on the right track, but when I click the add button to add a movie to the watch later session, but is unsuccessful. Any help would be much appreciated, thanks.

For the User experience, I am trying to make it so that when the user clicks add next to their preferred movie, it would be added to the watch later section. Here, under the watch later section, if the user decides to change their mind, they can click remove to remove the movie from this watch later section.

Below is some of the code I've created.

<HTML>

<head>
<meta charset="UTF-8" />
<link rel="stylesheet" href="lib/style.css" />
<script src="https://unpkg.com/vue@2" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/brython@3/brython.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/brython@3/brython_stdlib.js"></script>
</head>

<body onload="brython()">
<div id="app">
    <form @submit.prevent="toggleWatchLater('Mickey 17')">
        <label>Mickey 17</label>
        <input type="submit" value="Add">
    </form>

    <form @submit.prevent="toggleWatchLater('Oppenheimer')">
        <label>Oppenheimer</label>
        <input type="submit" value="Add">
    </form>

    <form @submit.prevent="toggleWatchLater('Dead Poets Society')">
        <label>Dead Poets Society</label>
        <input type="submit" value="Add">
    </form>

    <div id="WatchLater">
        <h2>Watch Later</h2>
        <ul>
            <li v-for="(movie, index) in watchLater" :key="index">
                <h4>{{ movie }}
                    <button @click="removeFromWatchLater(index)">Remove</button>
                </h4>
            </li>
        </ul>
    </div>
</div>

<script type="text/python">
    from browser import window

    def toggleWatchLater(self, movie_title, *_):
        if movie_title in self.watchLater:
            self.watchLater.remove(movie_title)
        else:
            self.watchLater.append(movie_title)

    def removeFromWatchLater(self, index):
        self.watchLater.pop(index)

    app = window.Vue.new({
        'el': '#app',
        'data': {
            'watchLater': []
        },
        'methods': {
            'toggleWatchLater': toggleWatchLater,
            'removeFromWatchLater': removeFromWatchLater
        }
    })
</script>

Solution

  • I don't know Vue but I think using self is wrong idea.
    It may not send any value which you could assign to self.

    Code works for me if I use directly app instead of self
    and I remove self from list of parameters

    def toggleWatchLater(movie_title, *_):
        if movie_title in app.watchLater:
            app.watchLater.remove(movie_title)
        else:
            app.watchLater.append(movie_title)
    
    def removeFromWatchLater(index):
        app.watchLater.pop(index)
    

    Full code used for tests.

    <HTML>
    
    <head>
    <meta charset="UTF-8" />
    <link rel="stylesheet" href="lib/style.css" />
    <script src="https://unpkg.com/vue@2" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/brython@3/brython.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/brython@3/brython_stdlib.js"></script>
    </head>
    
    <body onload="brython()">
    <div id="app">
        <form @submit.prevent="toggleWatchLater('Mickey 17')">
            <label>Mickey 17</label>
            <input type="submit" value="Add">
        </form>
    
        <form @submit.prevent="toggleWatchLater('Oppenheimer')">
            <label>Oppenheimer</label>
            <input type="submit" value="Add">
        </form>
    
        <form @submit.prevent="toggleWatchLater('Dead Poets Society')">
            <label>Dead Poets Society</label>
            <input type="submit" value="Add">
        </form>
    
        <div id="WatchLater">
            <h2>Watch Later</h2>
            <ul>
                <li v-for="(movie, index) in watchLater" :key="index">
                    <h4>{{ movie }}
                        <button @click="removeFromWatchLater(index)">Remove</button>
                    </h4>
                </li>
            </ul>
        </div>
    </div>
    
    <script type="text/python">
        from browser import window
    
        def toggleWatchLater(movie_title, *_):
            if movie_title in app.watchLater:
                app.watchLater.remove(movie_title)
            else:
                app.watchLater.append(movie_title)
    
        def removeFromWatchLater(index):
            app.watchLater.pop(index)
    
        app = window.Vue.new({
            'el': '#app',
            'data': {
                'watchLater': []
            },
            'methods': {
                'toggleWatchLater': toggleWatchLater,
                'removeFromWatchLater': removeFromWatchLater
            }
        })
    </script>
    

    UPDATE:

    Brython has javascript.this() which can be used similar to this in pure JavaScript - and you can use it in place of self and without self as parameter.

    (it is not directly JavaScript but very similar to pure JavaScript - so I don't know what with restriction "no javascript allowed")

    import javascript
    
    def toggleWatchLater(movie_title, *_):
        this = javascript.this()
        if movie_title in this.watchLater:
            this.watchLater.remove(movie_title)
        else:
            this.watchLater.append(movie_title)
    
    def removeFromWatchLater(index):
        this = javascript.this()
        this.watchLater.pop(index)
    

    Brython doc: module javascript


    Full working code:

    <HTML>
    
    <head>
    <meta charset="UTF-8" />
    <link rel="stylesheet" href="lib/style.css" />
    <script src="https://unpkg.com/vue@2" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/brython@3/brython.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/brython@3/brython_stdlib.js"></script>
    </head>
    
    <body onload="brython()">
    <div id="app">
        <form @submit.prevent="toggleWatchLater('Mickey 17')">
            <label>Mickey 17</label>
            <input type="submit" value="Add">
        </form>
    
        <form @submit.prevent="toggleWatchLater('Oppenheimer')">
            <label>Oppenheimer</label>
            <input type="submit" value="Add">
        </form>
    
        <form @submit.prevent="toggleWatchLater('Dead Poets Society')">
            <label>Dead Poets Society</label>
            <input type="submit" value="Add">
        </form>
    
        <div id="WatchLater">
            <h2>Watch Later</h2>
            <ul>
                <li v-for="(movie, index) in watchLater" :key="index">
                    <h4>{{ movie }}
                        <button @click="removeFromWatchLater(index)">Remove</button>
                    </h4>
                </li>
            </ul>
        </div>
    </div>
    
    <script type="text/python">
        from browser import window
        import javascript
    
        def toggleWatchLater(movie_title, *_):
            this = javascript.this()
            if movie_title in this.watchLater:
                this.watchLater.remove(movie_title)
            else:
                this.watchLater.append(movie_title)
    
        def removeFromWatchLater(index):
            this = javascript.this()
            this.watchLater.pop(index)
    
        app = window.Vue.new({
            'el': '#app',
            'data': {
                'watchLater': []
            },
            'methods': {
                'toggleWatchLater': toggleWatchLater,
                'removeFromWatchLater': removeFromWatchLater,
            }
        })
    </script>