diff --git a/js/vips.js b/js/vips.js
index 30c7322dce382d682b617e646d38fb2cee48f66f..4cff3da5812a5f254ccfd1643dbf3a382c8660d9 100644
--- a/js/vips.js
+++ b/js/vips.js
@@ -254,37 +254,29 @@ $(function() {
     });
 
     $('.dynamic_list').each(function() {
-        $(this).children('.dynamic_row').each(function(i) {
+        $(this).children('.dynamic_row, template').each(function(i) {
             $(this).data('index', i);
         });
     });
 
     $(document).on('click', '.add_dynamic_row', function(event) {
         var container = $(this).closest('.dynamic_list');
-        var template = container.children('.template').last();
-        var clone = template.clone(true).removeClass('template');
-        var index = template.data('index');
+        var template = container.children('template').last();
+        var clone = $(template.prop('content').cloneNode(true));
+        var index = template.data('index') ?? 0;
+        var loop = template.data('loop') ?? 'i';
+        var vars = Object.assign({[loop]: index}, template.data('vars'));
 
         template.data('index', index + 1);
-        clone.insertBefore(template);
-        clone.find('input[data-name], select[data-name], textarea[data-name]').each(function(i) {
-            if ($(this).data('name').indexOf(':') === 0) {
-                $(this).data('name', $(this).data('name').substr(1) + '[' + index + ']');
-            } else {
-                $(this).attr('name', $(this).data('name') + '[' + index + ']');
-                $(this).removeAttr('data-name');
-            }
+        clone.find('template').data('vars', vars);
+        clone.find('input[name], select[name], textarea[name]').each(function(i) {
+            $(this).attr('name', $(this).attr('name').replace(/\w+/g, match => vars[match] ?? match));
         });
-        clone.find('input[data-value], select[data-value], textarea[data-value]').each(function(i) {
-            if ($(this).data('value').indexOf(':') === 0) {
-                $(this).data('value', $(this).data('value').substr(1));
-            } else {
-                $(this).attr('value', index);
-                $(this).removeAttr('data-value');
-            }
+        clone.find('input[value], select[value], textarea[value]').each(function(i) {
+            $(this).attr('value', $(this).attr('value').replace(/\w+/g, match => vars[match] ?? match));
         });
-        clone.find('.wysiwyg-hidden:not(.template *)').toggleClass('wysiwyg wysiwyg-hidden');
-        clone.find('.add_dynamic_row:visible').click();
+        clone.insertBefore(template);
+        template.prev().find('.add_dynamic_row').click();
         event.preventDefault();
     });
 
diff --git a/views/exercises/sc_exercise/edit.php b/views/exercises/sc_exercise/edit.php
index 33fb793db1709e437b5a806d074f48154eaebcf2..c6fecd525835bbc60916149ee1ac49b59d2f7e0b 100644
--- a/views/exercises/sc_exercise/edit.php
+++ b/views/exercises/sc_exercise/edit.php
@@ -34,50 +34,56 @@
                 </div>
             <? endforeach ?>
 
-            <div class="dynamic_row mc_row template">
-                <label class="dynamic_counter size_toggle size_small undecorated">
-                    <?= $this->render_partial('exercises/flexible_input', ['data_name' => "answer[$j]", 'size' => 'small']) ?>
-                </label>
+            <template data-loop="i">
+                <div class="dynamic_row mc_row">
+                    <label class="dynamic_counter size_toggle size_small undecorated">
+                        <?= $this->render_partial('exercises/flexible_input', ['name' => "answer[$j][i]", 'size' => 'small']) ?>
+                    </label>
 
-                <label class="undecorated" style="padding: 1ex;">
-                    <input type="radio" name="correct[<?= $j ?>]" data-value>
-                    <?= _vips('richtig') ?>
-                </label>
+                    <label class="undecorated" style="padding: 1ex;">
+                        <input type="radio" name="correct[<?= $j ?>]" value="i">
+                        <?= _vips('richtig') ?>
+                    </label>
 
-                <a href="#" class="delete_dynamic_row">
-                    <?= Icon::create('trash', 'clickable', ['title' => _vips('Antwort löschen')]) ?>
-                </a>
-            </div>
+                    <a href="#" class="delete_dynamic_row">
+                        <?= Icon::create('trash', 'clickable', ['title' => _vips('Antwort löschen')]) ?>
+                    </a>
+                </div>
+            </template>
 
             <?= Studip\Button::create(_vips('Antwort hinzufügen'), 'add_answer', ['class' => 'add_dynamic_row']) ?>
             <?= Studip\Button::create(_vips('Antwortblock löschen'), 'del_group', ['class' => 'delete_dynamic_row']) ?>
         </div>
     <? endforeach ?>
 
-    <div class="dynamic_list dynamic_row template" style="border-bottom: 1px dotted grey;">
-        <label class="hide_first">
-            <?= _vips('Zwischentext') ?>
-            <textarea data-name="description" class="character_input size-l wysiwyg-hidden"></textarea>
-        </label>
-
-        <div class="dynamic_row mc_row template">
-            <label class="dynamic_counter size_toggle size_small undecorated">
-                <?= $this->render_partial('exercises/flexible_input', ['data_name' => ':answer', 'size' => 'small']) ?>
+    <template data-loop="j">
+        <div class="dynamic_list dynamic_row" style="border-bottom: 1px dotted grey;">
+            <label class="hide_first">
+                <?= _vips('Zwischentext') ?>
+                <textarea name="description[j]" class="character_input size-l wysiwyg"></textarea>
             </label>
 
-            <label class="undecorated" style="padding: 1ex;">
-                <input type="radio" data-name="correct" data-value=":value">
-                <?= _vips('richtig') ?>
-            </label>
+            <template data-loop="i">
+                <div class="dynamic_row mc_row">
+                    <label class="dynamic_counter size_toggle size_small undecorated">
+                        <?= $this->render_partial('exercises/flexible_input', ['name' => 'answer[j][i]', 'size' => 'small']) ?>
+                    </label>
 
-            <a href="#" class="delete_dynamic_row">
-                <?= Icon::create('trash', 'clickable', ['title' => _vips('Antwort löschen')]) ?>
-            </a>
-        </div>
+                    <label class="undecorated" style="padding: 1ex;">
+                        <input type="radio" name="correct[j]" value="i">
+                        <?= _vips('richtig') ?>
+                    </label>
+
+                    <a href="#" class="delete_dynamic_row">
+                        <?= Icon::create('trash', 'clickable', ['title' => _vips('Antwort löschen')]) ?>
+                    </a>
+                </div>
+            </template>
 
-        <?= Studip\Button::create(_vips('Antwort hinzufügen'), 'add_answer', ['class' => 'add_dynamic_row']) ?>
-        <?= Studip\Button::create(_vips('Antwortblock löschen'), 'del_group', ['class' => 'delete_dynamic_row']) ?>
-    </div>
+            <?= Studip\Button::create(_vips('Antwort hinzufügen'), 'add_answer', ['class' => 'add_dynamic_row']) ?>
+            <?= Studip\Button::create(_vips('Antwortblock löschen'), 'del_group', ['class' => 'delete_dynamic_row']) ?>
+        </div>
+    </template>
 
     <?= Studip\Button::create(_vips('Antwortblock hinzufügen'), 'add_group', ['class' => 'add_dynamic_row']) ?>
 </div>