peerlibrary / meteor-blaze-components

Reusable components for Blaze
http://components.meteorapp.com/
BSD 3-Clause "New" or "Revised" License
354 stars 26 forks source link

How to get targeted element? #105

Closed kokjinsam closed 9 years ago

kokjinsam commented 9 years ago

I'm stuck on this for two days now. It would be greatly appreciated if you can help me out on this. Here's my case:

I have a component named Component A. For this component, users are allowed to configure the component. For example, setting the width of the component.

ComponentA = BlazeComponent.extendComponent({
  template: function() {
    return 'my_template';
  },

  onRendered: function() {
    // here I want to target div with my-class and apply corresponding configurations
   // the problem only occurs when there are two ComponentA's
  }
}).register('ComponentA');
<template name="my_template">
   <div class="my-class">
      Here is the problem
   </div>
</template>

On user side:

{{# ComponentA args width=300 edge='left'}}
    Component 1
{{/ ComponentA }}

{{# ComponentA args width=240 edge='right'}}
    Component 2
{{/ ComponentA }}

Currently I'm using a hacky way to deal with this problem, which is to ask user specify the node index like document.getElementsByClassName('my-class')[nodeIndex]. Is there a way to get the targeted div in Blaze Component?

mitar commented 9 years ago

What is targeted div? Can you show code of your onRendered, the best version you believe that should work?

kokjinsam commented 9 years ago
onRendered: function() {
  var _this = this,
  drawer = _this.drawer,
  drawerTarget = document.getElementsByClassName('km-drawer')[drawer.nodeIndex],
  buttonTarget = document.getElementsByClassName('km-drawer__button')[drawer.nodeIndex];

        /**
         * set drawer width
         * then append drawer to drawer location
         **/
        var widthpx = drawer.width+'px';
        drawerTarget.style.width = widthpx;
        console.log('styled drawer '+drawer.nodeIndex);

        if(drawer.location === 'body') {
            document.body.insertBefore(drawerTarget, document.body.firstChild);
        }else{
            var location = document.getElementsByClassName(drawer.location);

            if(location[0] == undefined) {
                location = document.getElementById(drawer.location);
                if(location != undefined) {
                    location.insertBefore(drawerTarget, location.firstChild);
                }
            }else{
                location[0].insertBefore(drawerTarget, location[0].firstChild);
            }
        }

        /**
         * initialize drawer
         * toggle drawer open when on large screens and close when on small screens
         * add touch area for drawer
         * listen to resize event, toggle drawer according to screen sizes
         * remove left/right = 0 , drag target and overlay if type is fixed drawer
         **/
        var dragArea = document.createElement('div');
                dragArea.classList.add("km-drawer__drag-target");

        if (window.innerWidth > drawer.breakpoint) {
            _this._setDrawer('open');
        }else{
            document.body.appendChild(dragArea);
            _this._setDrawer('close');
        }

        var dragTargets = document.getElementsByClassName('km-drawer__drag-target');
                dragTarget = dragTargets[drawer.nodeIndex];

        window.addEventListener('resize', function() {
            var overlay = document.getElementById('km-drawer__overlay');

            if(window.innerWidth > drawer.breakpoint) {
                _this._setDrawer('open');

                if(drawer.type === 'fixed') {
                    document.body.removeAttribute('style');

                    dragTarget.style.width = '10px';
                    dragTarget.style.display = 'hidden';

                    if(overlay != null){
                        overlay.remove();
                    }
                }
            }else{
                dragTarget.style.display = 'initial';
                _this._setDrawer('close');
            }
        });
kokjinsam commented 9 years ago

By targeted div, I mean each component will have a div with class 'km-drawer'. Now I have different configurations for each component. How do I target the correct div? I hope that that makes sense.

mitar commented 9 years ago

You should be using this.$('.km-drawer') and not global document.getElementsByClassName.

mitar commented 9 years ago

Also, the whole your approach is bad. You should really not be modifying DOM manually. You should use Blaze to render and change the content. Having everything done manually inside a Blaze Component somehow defeats the purpose of using Blaze Components and you are then fighting the system.

kokjinsam commented 9 years ago

I try not to use Jquery, how should I go about that?

I'm kinda new to Meteor, I'm still part of the learning process. Thanks for letting me know!

mitar commented 9 years ago

jQuery is part of the Blaze and Meteor framework.

kokjinsam commented 9 years ago

ahh. OK. Thanks again for helping!