0

Edit: Similar but slightly different question can be found here: Vue.js : How to set a unique ID for each component instance?

I'm trying to create a table so that someone can check the people they want to add to a group. So far I've managed to retrieve them from the DB with PHP and display them with vue in HTML. Now I would like to assign each checkbox ID with the email of the student, so i can send the checked students back to PHP later. There may be (a lot) better ways to do this, but I'm very new to this.

This is my current output: My Output

My HTML:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8">
    <!-- Axios -->
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>

    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

</head>

<body>

    <div id="vue-app">
        <table>
            <thead>
                <tr>
                    <th>Select</th>
                    <th>Firstname</th>
                    <th>Lastname</th>
                </tr>
            </thead>
            <tbody>
                <tr v-for="(student, index) in students">
                <input type="checkbox" id="{{student.email}}">
                <td>{{student.firstname}}</td>
                <td>{{student.lastname}}</td>
                </tr>
            </tbody>
        </table>
    </div>

 var app = new Vue({

            el: '#vue-app',
            data: {
                students: []
            },
            mounted: function () {
                axios.get('get_students_list.php')
                    .then(response => {
                        this.students = response.data;
                        console.log(students);
                    })
                    .catch(error => {
                        console.log(error);
                    });
            }
        })

get_students_list.php:

try {
include("db_connection.php");
$isteacher = false;

$query = "SELECT firstname, lastname, email FROM persons WHERE isteacher = :isteacher";
$statement = $conn->prepare($query);
$statement->bindParam(':isteacher', $isteacher);

$statement->execute();

//gets row as associative array
$users = $statement->fetchAll(PDO::FETCH_ASSOC);


$students = json_encode($users);
echo $students;

} catch (PDOException $error) {
echo $error;
}

I've tried the above id allocation and I also tried creating a checkbox with javascript with the following code (which didn't work either, because for one i can't acces the vue elements from there):

                var checkbox = document.createElement('input');
                checkbox.type = "checkbox";
                checkbox.id = {{student.email}};
                checkbox.checked = false; 

Additional tries:

<input type="checkbox" v-bind:id="student.email">

and

<input type="checkbox" :id="student.email">
Oliver
  • 117
  • 2
  • 15
  • As written in the answer below, you need to bind the id attribute using v-bind. Simply using id="{{...}}" does not interpolate the template variable but inserts it verbatim. – wwerner Dec 26 '19 at 12:21
  • Yes but the mentioned code doesn't work either. I tried v-bind:id and just :id but both throw an error in my code. – Oliver Dec 26 '19 at 12:47
  • Don't use {{...}} in the attribute, see link to the docs below. – wwerner Dec 26 '19 at 12:50
  • Sorry i forgot to take that out of the post, i don't have that in my code anymore anyway. – Oliver Dec 26 '19 at 12:51
  • Also, continuously editing the question makes it very hard for readers to see what is going on; rather add to your question what you already tried, so others can follow. – wwerner Dec 26 '19 at 12:51

1 Answers1

1

Note: This refers to the last snippet shown in the question, as the OP changed the question after this answer.

Assuming the server side code & fetching the data works, you don't need to create the input element by another script, you can simple create it like you do with the <td> elements in the v-for loop:

<tr v-for="(student, index) in students">
  <input type="checkbox" :id="student.email"
  <td>{{student.email}}</td>
  <td>{{student.lastname}}</td>
</tr>

Note the : (or v-bind: as the verbose option) before the id attribute, this is used to bind data to attributes. See https://v2.vuejs.org/v2/guide/syntax.html#Attributes

Edit: Added working example: https://codesandbox.io/s/stack-overflow-q-59488184-x8m0w

Edit: You also need to bind the result to the vue instance. this in .then does not point to your component. Use a closure for that:

 mounted() {
    let vm = this;
    axios
      .get("..."
      .then(response => {
        vm.students = response.data;
        console.log(vm.students);
      })
tony19
  • 125,647
  • 18
  • 229
  • 307
wwerner
  • 4,227
  • 1
  • 21
  • 39
  • When i try this code following error appears: "Vue warn]: Property or method "student" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property." and this "[Vue warn]: Error in render: "TypeError: Cannot read property 'email' of undefined" – Oliver Dec 26 '19 at 12:20
  • Thank you so much! I don't quite understand it yet - with me it only works when pasting the code into the same file, but at least it works - so i have a good basis to work on. Thanks! – Oliver Dec 26 '19 at 13:31