2

I may have gone about this completely the wrong way from the beginning so all advise is welcomed.

I am trying to create a basic page with inputs on the right and hints for the inputs on the left and when you focus on the inputs the appropriate hint is highlighted on the left.

There is a JSFiddle here: https://jsfiddle.net/eywraw8t/210693/

This will not work as I do not know how to find the appropriate hint to highlight (and set isHighlighted to false on all the other hints).

I managed to get a working example by adding a highlighted prop on the field object and not using a hint component. However in reality the fields data will come from the database so it won't have a highlighted parameter so a hint component seemed more sensible.

To put my question in simple terms: How can I find the relevant hint component when focused on an input?

JS Fiddle showing functionality without a component: https://jsfiddle.net/as2vxy79/

Broken JS Fiddle trying to use a component: https://jsfiddle.net/eywraw8t/210693/

Here is the JS outside JS Fiddle:

Vue.component('hint', {
    template: `
    <div class="hint" :class="{'highlight-hint': isHighlighted }">
      <slot></slot>
    </div>
  `,
  data() {
    return {
        isHighlighted: false
    }
  }
});

new Vue({
  el: "#app",
  data: {
    fields: [
      {
        'id': 'name',
        'hint': 'Put the name here'
      },
      {
        'id': 'description',
        'hint': 'Put the description here'
      },
      {
        'id': 'more',
        'hint': 'Put more here'
      }
    ]
  },
  methods: {
    onFocus(focusedField) {
        // Somehow loop through the hints
      // I am aware there is no "hints" property this is an example
      this.hints.forEach(function(field) {
        field.isHighlighted = (focusedField == field.id)
      })
    }
  }
})
1
  • "the fields data will come from the database so it won't have a highlighted parameter", why does that prevent you from adding it? You shouldn't be telling the component that it is highlighted, you should be setting it on the data as you are in your working example and letting the component learn, from the data, that it should be highlighted. Commented Jul 26, 2018 at 15:37

1 Answer 1

3

Short answer: you don't need a direct reference to the components displaying the hint because you can solve this problem using reactivity.

Only thing you need to do is add a data field which stores the field id you want to highlight and then conditionally add a class to the hint you want to highlight based on the selected id (or render the components conditionally).

new Vue({
  el: "#app",
  data: {
    highlightedFieldId: '',
    fields: [
      {
        'id': 'name',
        'hint': 'Put the name here'      },
      {
        'id': 'description',
        'hint': 'Put the description here'      },
      {
        'id': 'more',
        'hint': 'Put more here'      }
    ]
  },
  methods: {
    onFocus(focusedFieldId) {
      this.highlightedFieldId = focusedFieldId;
    }
  }
})

Here's an update to your Fiddle.


NOTES:

  • If you really need direct references you can use the ref directive (this also works in a list of components generated by v-for).
  • You should probably think about using tooltips for the hints. E.g. using Element UI's Tooltip.

UPDATE:

So, here's a solution using the ref directive to obtain a reference to the highlighted hint component. You can see that I used the field id in :ref but you still get an array from this.$refs[focusedFieldId] since there is a surrounding v-for. Other than that, it's pretty simple.

I also updated the hint component to accept the is-highlighted prop so it can change its class on its own (you previously used a data property for this which does not result in a component update).

Sign up to request clarification or add additional context in comments.

5 Comments

Cheers that's awesome. I realised I may also need to scroll the hint into view so being able to access the specific hint via ref would be great. Are you able to explain that? Simply using ref="hints" on the component results in a non-associative array so it's not clear how to access the appropriate hint.
And in regards the tooltip, each hint may be quite large (2/3 paragraphs) hence a guide in the sidebar that scrolls into view seems more appropriate :)
@robjbrain Ok, yeah, this probably is too much for a tooltip. ; ) Check my update for an example of how to get the component reference using the ref directive.
Thanks, i've accepted your answer because it definitely resolves the original question although i'm still a little unsure how to work with the component within $ref, standard methods such as .scrollIntoView() don't seem to be available. Although this is probably more a basic naivety of vuejs and I need to do some more reading/practising.
Thanks! This is simple as well. You just need to access $el on the hint component obtained from the $refs collection: this.$refs[focusedFieldId][0].$el gives you the native element which is the root node of the hint component. From there you can work with scrollIntoView or Window.scrollTo: see here. Good luck!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.