Dynamically Tally Child Elements by Classname in Vue












0














I have a page that allows a user to drag/drop images into pre-defined DIVs, then I tally up the total value of the images based on their class name. What I am trying to do is get vue to read the values from each outer div.answer and get the class names of the child images.



My source code is:



<div
is="box-answers"
v-for="box in boxes.slice().reverse()"
v-bind:key="box.id"
v-bind:level="box.level"
v-bind:hint="box.hint"
></div>

<script>
Vue.component('box-answers', {
props: ['level','hint'],
template: '<div class="droppable answer :id="level" :title="hint"></div>'
});

new Vue({
el: '#mainapp',
data: {
boxes: [
{ id: 1, level: 'baselevel-1', hint: 'x 1' },
{ id: 2, level: 'baselevel-2', hint: 'x 20' },
{ id: 3, level: 'baselevel-3', hint: 'x 400' },
{ id: 4, level: 'baselevel-4', hint: 'x 8,000' },
{ id: 5, level: 'baselevel-5', hint: 'x 160,000' }
]
}
</script>


This converts to the follow HTML (the nested DIVs and SPANs are user-possible entries by dragging):



    <div id="baselevel-5" class="droppable answer" title="x 160,000">
<div><img src="images/line.gif" alt="Five" class="imgfive"></div>
<span><img src="images/dot.gif" alt="One" class="imgone"></span>
</div>
...
<div id="baselevel-1" class="droppable answer" title="x 1">
<span><img src="images/line.gif" alt="One" class="imgone"></span>
</div>


Currently, I have jQuery/JavaScript calculating the point values using the following:



$(function(j) {
var arAnswers = Array(1);
count = 0; //
j("div.answer").each(function( idx ) {
currentId = j(this).attr('id');
ones = 0;
fives = 0;

if ( j("#" + currentId).children().length > 0 ) {
ones = j("#" + currentId).children().find("img.imgone").length * 1;
fives = j("#" + currentId).children().find("img.imgfive").length * 5;
arAnswers[count] = ones + fives; //Tally box value

count++;
}
});
});


I would like Vue to perform similar iteration and addition to return total value of ones and fives found based on the image classname.










share|improve this question





























    0














    I have a page that allows a user to drag/drop images into pre-defined DIVs, then I tally up the total value of the images based on their class name. What I am trying to do is get vue to read the values from each outer div.answer and get the class names of the child images.



    My source code is:



    <div
    is="box-answers"
    v-for="box in boxes.slice().reverse()"
    v-bind:key="box.id"
    v-bind:level="box.level"
    v-bind:hint="box.hint"
    ></div>

    <script>
    Vue.component('box-answers', {
    props: ['level','hint'],
    template: '<div class="droppable answer :id="level" :title="hint"></div>'
    });

    new Vue({
    el: '#mainapp',
    data: {
    boxes: [
    { id: 1, level: 'baselevel-1', hint: 'x 1' },
    { id: 2, level: 'baselevel-2', hint: 'x 20' },
    { id: 3, level: 'baselevel-3', hint: 'x 400' },
    { id: 4, level: 'baselevel-4', hint: 'x 8,000' },
    { id: 5, level: 'baselevel-5', hint: 'x 160,000' }
    ]
    }
    </script>


    This converts to the follow HTML (the nested DIVs and SPANs are user-possible entries by dragging):



        <div id="baselevel-5" class="droppable answer" title="x 160,000">
    <div><img src="images/line.gif" alt="Five" class="imgfive"></div>
    <span><img src="images/dot.gif" alt="One" class="imgone"></span>
    </div>
    ...
    <div id="baselevel-1" class="droppable answer" title="x 1">
    <span><img src="images/line.gif" alt="One" class="imgone"></span>
    </div>


    Currently, I have jQuery/JavaScript calculating the point values using the following:



    $(function(j) {
    var arAnswers = Array(1);
    count = 0; //
    j("div.answer").each(function( idx ) {
    currentId = j(this).attr('id');
    ones = 0;
    fives = 0;

    if ( j("#" + currentId).children().length > 0 ) {
    ones = j("#" + currentId).children().find("img.imgone").length * 1;
    fives = j("#" + currentId).children().find("img.imgfive").length * 5;
    arAnswers[count] = ones + fives; //Tally box value

    count++;
    }
    });
    });


    I would like Vue to perform similar iteration and addition to return total value of ones and fives found based on the image classname.










    share|improve this question



























      0












      0








      0







      I have a page that allows a user to drag/drop images into pre-defined DIVs, then I tally up the total value of the images based on their class name. What I am trying to do is get vue to read the values from each outer div.answer and get the class names of the child images.



      My source code is:



      <div
      is="box-answers"
      v-for="box in boxes.slice().reverse()"
      v-bind:key="box.id"
      v-bind:level="box.level"
      v-bind:hint="box.hint"
      ></div>

      <script>
      Vue.component('box-answers', {
      props: ['level','hint'],
      template: '<div class="droppable answer :id="level" :title="hint"></div>'
      });

      new Vue({
      el: '#mainapp',
      data: {
      boxes: [
      { id: 1, level: 'baselevel-1', hint: 'x 1' },
      { id: 2, level: 'baselevel-2', hint: 'x 20' },
      { id: 3, level: 'baselevel-3', hint: 'x 400' },
      { id: 4, level: 'baselevel-4', hint: 'x 8,000' },
      { id: 5, level: 'baselevel-5', hint: 'x 160,000' }
      ]
      }
      </script>


      This converts to the follow HTML (the nested DIVs and SPANs are user-possible entries by dragging):



          <div id="baselevel-5" class="droppable answer" title="x 160,000">
      <div><img src="images/line.gif" alt="Five" class="imgfive"></div>
      <span><img src="images/dot.gif" alt="One" class="imgone"></span>
      </div>
      ...
      <div id="baselevel-1" class="droppable answer" title="x 1">
      <span><img src="images/line.gif" alt="One" class="imgone"></span>
      </div>


      Currently, I have jQuery/JavaScript calculating the point values using the following:



      $(function(j) {
      var arAnswers = Array(1);
      count = 0; //
      j("div.answer").each(function( idx ) {
      currentId = j(this).attr('id');
      ones = 0;
      fives = 0;

      if ( j("#" + currentId).children().length > 0 ) {
      ones = j("#" + currentId).children().find("img.imgone").length * 1;
      fives = j("#" + currentId).children().find("img.imgfive").length * 5;
      arAnswers[count] = ones + fives; //Tally box value

      count++;
      }
      });
      });


      I would like Vue to perform similar iteration and addition to return total value of ones and fives found based on the image classname.










      share|improve this question















      I have a page that allows a user to drag/drop images into pre-defined DIVs, then I tally up the total value of the images based on their class name. What I am trying to do is get vue to read the values from each outer div.answer and get the class names of the child images.



      My source code is:



      <div
      is="box-answers"
      v-for="box in boxes.slice().reverse()"
      v-bind:key="box.id"
      v-bind:level="box.level"
      v-bind:hint="box.hint"
      ></div>

      <script>
      Vue.component('box-answers', {
      props: ['level','hint'],
      template: '<div class="droppable answer :id="level" :title="hint"></div>'
      });

      new Vue({
      el: '#mainapp',
      data: {
      boxes: [
      { id: 1, level: 'baselevel-1', hint: 'x 1' },
      { id: 2, level: 'baselevel-2', hint: 'x 20' },
      { id: 3, level: 'baselevel-3', hint: 'x 400' },
      { id: 4, level: 'baselevel-4', hint: 'x 8,000' },
      { id: 5, level: 'baselevel-5', hint: 'x 160,000' }
      ]
      }
      </script>


      This converts to the follow HTML (the nested DIVs and SPANs are user-possible entries by dragging):



          <div id="baselevel-5" class="droppable answer" title="x 160,000">
      <div><img src="images/line.gif" alt="Five" class="imgfive"></div>
      <span><img src="images/dot.gif" alt="One" class="imgone"></span>
      </div>
      ...
      <div id="baselevel-1" class="droppable answer" title="x 1">
      <span><img src="images/line.gif" alt="One" class="imgone"></span>
      </div>


      Currently, I have jQuery/JavaScript calculating the point values using the following:



      $(function(j) {
      var arAnswers = Array(1);
      count = 0; //
      j("div.answer").each(function( idx ) {
      currentId = j(this).attr('id');
      ones = 0;
      fives = 0;

      if ( j("#" + currentId).children().length > 0 ) {
      ones = j("#" + currentId).children().find("img.imgone").length * 1;
      fives = j("#" + currentId).children().find("img.imgfive").length * 5;
      arAnswers[count] = ones + fives; //Tally box value

      count++;
      }
      });
      });


      I would like Vue to perform similar iteration and addition to return total value of ones and fives found based on the image classname.







      vue.js vuejs2






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 21 at 20:38









      marc_s

      570k12811021250




      570k12811021250










      asked Nov 21 at 2:50









      Angry Spartan

      1,79963666




      1,79963666
























          1 Answer
          1






          active

          oldest

          votes


















          2














          Currently, you are approaching this problem as a pure-play DOM operation. If that is what you need then you can simply use $refs:



          <!-- NOTICE ref -->
          <div ref="boxAnswers"
          is="box-answers"
          v-for="box in boxes.slice().reverse()"
          v-bind:key="box.id"
          v-bind:level="box.level"
          v-bind:hint="box.hint">
          </div>


          Inside your high-level component, you will have a function like:



          function calculate() {
          // NOTICE $refs
          const arAnswers = this.$refs.boxAnswers.map((x) => {

          // $el is the DOM element
          const once = x.$el.querySelectorAll('img.imgone').length * 1;
          const fives = x.$el.querySelectorAll('img.imgfive').length * 5;

          return once + fives

          });

          return arAnswers;

          }


          But this is not the correct Vue way of doing things. You have to think in terms of events and data model (MVVM - don't touch DOM. DOM is just a representation of your data model). Since, you have a drag-n-drop based application, you have to listen for drag, dragstart, dragend and other drag events. For example:



          <!-- NOTICE drop event -->
          <div @drop="onDropEnd(box, $event)"
          is="box-answers"
          v-for="box in boxes.slice().reverse()"
          v-bind:key="box.id"
          v-bind:level="box.level"
          v-bind:hint="box.hint">
          </div>


          Your onDropEnd event handler will look like:



          function onDrop(box, $event) {

          // box - on which box drop is happening
          // $event.data - which image is being dropped

          // Verify $event.data is actually the image you are intending
          if ($event.data === 'some-type-image') {
          // Do the counting manipulations here
          // ... remaining code
          }

          }


          This is not a complete code as I don't know other components. But it should help you with the required direction.






          share|improve this answer





















          • I'm still very new to Vue so while I understand why your first answer is not the real way to do it, I'll work with that one until I get a deeper understanding of the language. Using $refs has opened my eyes to lots of potential!
            – Angry Spartan
            Nov 23 at 13:55











          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53404630%2fdynamically-tally-child-elements-by-classname-in-vue%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          2














          Currently, you are approaching this problem as a pure-play DOM operation. If that is what you need then you can simply use $refs:



          <!-- NOTICE ref -->
          <div ref="boxAnswers"
          is="box-answers"
          v-for="box in boxes.slice().reverse()"
          v-bind:key="box.id"
          v-bind:level="box.level"
          v-bind:hint="box.hint">
          </div>


          Inside your high-level component, you will have a function like:



          function calculate() {
          // NOTICE $refs
          const arAnswers = this.$refs.boxAnswers.map((x) => {

          // $el is the DOM element
          const once = x.$el.querySelectorAll('img.imgone').length * 1;
          const fives = x.$el.querySelectorAll('img.imgfive').length * 5;

          return once + fives

          });

          return arAnswers;

          }


          But this is not the correct Vue way of doing things. You have to think in terms of events and data model (MVVM - don't touch DOM. DOM is just a representation of your data model). Since, you have a drag-n-drop based application, you have to listen for drag, dragstart, dragend and other drag events. For example:



          <!-- NOTICE drop event -->
          <div @drop="onDropEnd(box, $event)"
          is="box-answers"
          v-for="box in boxes.slice().reverse()"
          v-bind:key="box.id"
          v-bind:level="box.level"
          v-bind:hint="box.hint">
          </div>


          Your onDropEnd event handler will look like:



          function onDrop(box, $event) {

          // box - on which box drop is happening
          // $event.data - which image is being dropped

          // Verify $event.data is actually the image you are intending
          if ($event.data === 'some-type-image') {
          // Do the counting manipulations here
          // ... remaining code
          }

          }


          This is not a complete code as I don't know other components. But it should help you with the required direction.






          share|improve this answer





















          • I'm still very new to Vue so while I understand why your first answer is not the real way to do it, I'll work with that one until I get a deeper understanding of the language. Using $refs has opened my eyes to lots of potential!
            – Angry Spartan
            Nov 23 at 13:55
















          2














          Currently, you are approaching this problem as a pure-play DOM operation. If that is what you need then you can simply use $refs:



          <!-- NOTICE ref -->
          <div ref="boxAnswers"
          is="box-answers"
          v-for="box in boxes.slice().reverse()"
          v-bind:key="box.id"
          v-bind:level="box.level"
          v-bind:hint="box.hint">
          </div>


          Inside your high-level component, you will have a function like:



          function calculate() {
          // NOTICE $refs
          const arAnswers = this.$refs.boxAnswers.map((x) => {

          // $el is the DOM element
          const once = x.$el.querySelectorAll('img.imgone').length * 1;
          const fives = x.$el.querySelectorAll('img.imgfive').length * 5;

          return once + fives

          });

          return arAnswers;

          }


          But this is not the correct Vue way of doing things. You have to think in terms of events and data model (MVVM - don't touch DOM. DOM is just a representation of your data model). Since, you have a drag-n-drop based application, you have to listen for drag, dragstart, dragend and other drag events. For example:



          <!-- NOTICE drop event -->
          <div @drop="onDropEnd(box, $event)"
          is="box-answers"
          v-for="box in boxes.slice().reverse()"
          v-bind:key="box.id"
          v-bind:level="box.level"
          v-bind:hint="box.hint">
          </div>


          Your onDropEnd event handler will look like:



          function onDrop(box, $event) {

          // box - on which box drop is happening
          // $event.data - which image is being dropped

          // Verify $event.data is actually the image you are intending
          if ($event.data === 'some-type-image') {
          // Do the counting manipulations here
          // ... remaining code
          }

          }


          This is not a complete code as I don't know other components. But it should help you with the required direction.






          share|improve this answer





















          • I'm still very new to Vue so while I understand why your first answer is not the real way to do it, I'll work with that one until I get a deeper understanding of the language. Using $refs has opened my eyes to lots of potential!
            – Angry Spartan
            Nov 23 at 13:55














          2












          2








          2






          Currently, you are approaching this problem as a pure-play DOM operation. If that is what you need then you can simply use $refs:



          <!-- NOTICE ref -->
          <div ref="boxAnswers"
          is="box-answers"
          v-for="box in boxes.slice().reverse()"
          v-bind:key="box.id"
          v-bind:level="box.level"
          v-bind:hint="box.hint">
          </div>


          Inside your high-level component, you will have a function like:



          function calculate() {
          // NOTICE $refs
          const arAnswers = this.$refs.boxAnswers.map((x) => {

          // $el is the DOM element
          const once = x.$el.querySelectorAll('img.imgone').length * 1;
          const fives = x.$el.querySelectorAll('img.imgfive').length * 5;

          return once + fives

          });

          return arAnswers;

          }


          But this is not the correct Vue way of doing things. You have to think in terms of events and data model (MVVM - don't touch DOM. DOM is just a representation of your data model). Since, you have a drag-n-drop based application, you have to listen for drag, dragstart, dragend and other drag events. For example:



          <!-- NOTICE drop event -->
          <div @drop="onDropEnd(box, $event)"
          is="box-answers"
          v-for="box in boxes.slice().reverse()"
          v-bind:key="box.id"
          v-bind:level="box.level"
          v-bind:hint="box.hint">
          </div>


          Your onDropEnd event handler will look like:



          function onDrop(box, $event) {

          // box - on which box drop is happening
          // $event.data - which image is being dropped

          // Verify $event.data is actually the image you are intending
          if ($event.data === 'some-type-image') {
          // Do the counting manipulations here
          // ... remaining code
          }

          }


          This is not a complete code as I don't know other components. But it should help you with the required direction.






          share|improve this answer












          Currently, you are approaching this problem as a pure-play DOM operation. If that is what you need then you can simply use $refs:



          <!-- NOTICE ref -->
          <div ref="boxAnswers"
          is="box-answers"
          v-for="box in boxes.slice().reverse()"
          v-bind:key="box.id"
          v-bind:level="box.level"
          v-bind:hint="box.hint">
          </div>


          Inside your high-level component, you will have a function like:



          function calculate() {
          // NOTICE $refs
          const arAnswers = this.$refs.boxAnswers.map((x) => {

          // $el is the DOM element
          const once = x.$el.querySelectorAll('img.imgone').length * 1;
          const fives = x.$el.querySelectorAll('img.imgfive').length * 5;

          return once + fives

          });

          return arAnswers;

          }


          But this is not the correct Vue way of doing things. You have to think in terms of events and data model (MVVM - don't touch DOM. DOM is just a representation of your data model). Since, you have a drag-n-drop based application, you have to listen for drag, dragstart, dragend and other drag events. For example:



          <!-- NOTICE drop event -->
          <div @drop="onDropEnd(box, $event)"
          is="box-answers"
          v-for="box in boxes.slice().reverse()"
          v-bind:key="box.id"
          v-bind:level="box.level"
          v-bind:hint="box.hint">
          </div>


          Your onDropEnd event handler will look like:



          function onDrop(box, $event) {

          // box - on which box drop is happening
          // $event.data - which image is being dropped

          // Verify $event.data is actually the image you are intending
          if ($event.data === 'some-type-image') {
          // Do the counting manipulations here
          // ... remaining code
          }

          }


          This is not a complete code as I don't know other components. But it should help you with the required direction.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 21 at 5:40









          Harshal Patil

          2,11911139




          2,11911139












          • I'm still very new to Vue so while I understand why your first answer is not the real way to do it, I'll work with that one until I get a deeper understanding of the language. Using $refs has opened my eyes to lots of potential!
            – Angry Spartan
            Nov 23 at 13:55


















          • I'm still very new to Vue so while I understand why your first answer is not the real way to do it, I'll work with that one until I get a deeper understanding of the language. Using $refs has opened my eyes to lots of potential!
            – Angry Spartan
            Nov 23 at 13:55
















          I'm still very new to Vue so while I understand why your first answer is not the real way to do it, I'll work with that one until I get a deeper understanding of the language. Using $refs has opened my eyes to lots of potential!
          – Angry Spartan
          Nov 23 at 13:55




          I'm still very new to Vue so while I understand why your first answer is not the real way to do it, I'll work with that one until I get a deeper understanding of the language. Using $refs has opened my eyes to lots of potential!
          – Angry Spartan
          Nov 23 at 13:55


















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.





          Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


          Please pay close attention to the following guidance:


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53404630%2fdynamically-tally-child-elements-by-classname-in-vue%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Wiesbaden

          Marschland

          Dieringhausen