Enabling a button when >2 characters entered in textbox

Hi guys, Blaze beginner here. I’m trying to enable a “button” when more than two characters are entered into a “textbox”. I’m trying to use a “helper” but I somehow cannot get the value of the textbox (individual-name).

Here’s my JS code:

        const individualName = Template.instance().state.get('individual-name');
        if (individualName !== undefined && individualName.length > 2) {
            return '';
        }
        return 'disabled';
    },

Corresponding HTML:

                            <form class="newIndividual text-center margin-bottom20">
                                <div class="input-group" style="width: 100%">
                                    <label for="individual-name" class="input-label">Add the full name of the individual (minimum 3 letters)</label>
                                    <input type="text" class="form-control interested text-center required" name="individual-name" id="individual-name">
                                </div>
                            </form>
                            <button class="btn btn-own-orange js-newftPerson-upload" {{enableUploadBtn2}}>Upload File</button>
                        </div>

I don’t want to use jQuery, this should be possible in Blaze, right?

It’s been a while, but I think your logic should be: individualName?.value?.length > 2
Try console.dir(individualName) to see what exctly you are getting.

Hi Jan,

thanks for your reply. That part isn’t the problem.

I’ve tried a helper (which is the first JS code listed above) but somehow the helper is only called once. At that moment there’s nothing in the text field.

In the meantime I have reacting to the keyup event with the following code:

'keyup #individual-name': function (event, templateInstance) {
        if ($(event.currentTarget).val().length > 2) {
            templateInstance.state.set('js-newftPerson-upload', '');
        } else {
            templateInstance.state.set('js-newftPerson-upload', 'disabled');
        }
    },

However with this alternative I do have the problem that both the disabling part and the enabling of the button doesn’t work at all (the if and else part works fine).

Here’s the approach I used a while back:

HTML

<input type='text' class='textarea'>
<button class='button' {{disabled}}>Submit</button>

JS

Template.submit.onCreated(function() {
  var instance = this;
  instance.characterCount = new ReactiveVar(0);
})

Template.submit.helpers({
  disabled: function() {
    return Template.instance().characterCount.get() > 0 ? '' : 'disabled'
  }
})

Template.submit.events({
  'input .textarea': function(event, template) {
    let textarea = event.currentTarget;

    template.characterCount.set(textarea.textContent.length);
  }
})

As an aside, I still think Blaze is great but I’ve enjoyed using Svelte even more, especially for things like this. There’s a lot less syntax involved.

1 Like

Thank you @jam for your help, your code has finally enabled me to solve this problem!

Key for this was to use ReactiveVar, initialize it in the onCreated and update it either with input or keyup event (both work).

For reference, here is the code that I used finally:

HTML:

<label for="individual-name" class="input-label">Add the full name of the individual (minimum 3 letters)</label>
                                    <input type="text" class="form-control text-center" name="individual-name" id="individual-name">

JS:

import { ReactiveVar } from 'meteor/reactive-var';

Template.rawDnaImport.onCreated(function () {
   instance.characterCount = new ReactiveVar(0);
});

Template.rawDnaImport.helpers({
   disabled() {
        return Template.instance().characterCount.get() > 2 ? '' : 'disabled';
    },
});

Template.rawDnaImport.events({
   'keyup #individual-name': function (event, templateInstance) {
        templateInstance.characterCount.set(event.currentTarget.value.length);
    },
});

As a total beginner to Blaze or frontend frameworks in general I find it very difficult to even fix problems in another developers frontend code. It might be coding style/experience but the fact that Blaze has CSS, HTML and JS in 3 different files makes it very confusing.

Not only did I discover some unused CSS references (maybe just lazily copied from other code - but there’s no easy way to tell it’s not used) but constantly switching between the HTML and JS file that holds the code to one, single modal is cumbersome.

I haven’t looked into Svelte or Vue for that matter if they resolve this by keeping all nicely in one, single file (component). Sorry for not knowing these basics but I’m fully occupied with all the backend code and infrastructure and each time I have to change/fix the existing (monster) of frontend code a lot of my precious time is lost.

So thanks to everyone who tried to help me, it’s highly appreciated and it surely won’t be the last time I’m asking for help.

If anyone is interested in getting paid for helping on what I think are short & easy fixes/UI changes in Blaze/HTML if they arise (so can be easily done on top of an existing full-time work) please contact me via PM.

1 Like

As you mention you’re a beginner with frontend frameworks, it will indeed seem a little strange. For my company’s client work, we make heavy use of Vue, which is great. But we also have a six year old Meteor app that still uses Blaze, which is great as well. Getting the hang of the two files (.js and .html) becomes second nature. If it helps, think of the JS file as the controller, and the HTML file as the view. When Blaze came out, I don’t think there were many if any frameworks that made use of the single-file approach, so Blaze can seem dated these days but it’s still powerful for many use cases.

We use Vue on its own as well as within a couple Nuxt apps we’ve built, and the single file HTML/JS/CSS is nice, but certainly not a game changer. Vue itself is a game changer for templates and reactivity, but if it was two/three files it wouldn’t bother us. Especially with VS Code and the ability to have two editors via “split down”, you can have your .html on top and .js on bottom. :smiley:

Hi Mike,

maybe I should make my comment a bit more relevant. I have a growing feeling it’s not just Blaze but also the original developers coding style. To give an example:

<input type="text" class="form-control text-center" name="individual-name" id="individual-name">

I’ve already cleaned out several CSS elements from this line that were just copied over. What I find strange in here is that I don’t know if name or id is being used in the JS code as the reference to this HTML code. Why is both being used in here?

I’m using WebStorm but surely it’s possible to “solve” this visual problem. But it doesn’t change the fact that it would be a lot easier to identify (in my specific case) unnecessary and convoluted code references (eg CSS elements or the above example of name/id usage).

So I think it’s beyond convenience to have all necessary information in one file. It’s about ensuring that your CSS elements aren’t constantly overwritten somewhere else, leading to things like this (again, actual example from my app):
CSS example

Might be just me but having buttons not being perfectly aligned and different font size is just triggering my OCD - solving this simple example is a nightmare for my (at least with the current code base).

1 Like

Yes, css scoped to the component is great. It avoids all sorts of weird issues like the ones you’re pointing out.

Both are component based. I looked at Vue first and almost went with it until I found Svelte. It has all the benefits of Blaze but you end up writing a lot less code.

1 Like

It’s often not easy to take over a previous developer’s work. There could be many reasons to use the name/class/id attributes. Name attributes are important for forms in general. In your case, I would just search individual-name in your JS file to see how the event listener is bound.

CSS architecture is not an easy problem to solve, but when done well you can reuse selector rules across all components rather than writing more CSS that can contribute to bloat. In our projects, we find this approach keeps design language consistent across the app, and keeps CSS rules to as minimal as possible since CSS is render blocking.

Just FYI, this kind of stuff is trivial and also quite elegant in Vue - (the same is also true React/Svelte as well, but Vue is my personal favorite)

<button class"..." :disabled="individualName.length < 3">Upload File</button>

Or, if there are more inputs to validate, or you prefer to keep your logic out of the templates:

<button class"..." :disabled="!isValid">Upload File</button>
...
</template>
<script>

export default {
    ...
    computed: {
        isValid() {
            return this.individualName.length > 2;
        },

IMO it’s definitely worth investing the time leaning one of the newer front-end frameworks. Blaze was good, but it’s been left behind. We converted an entire commercial project from Blaze to Vue and it actually didn’t take that long, reduced the code by a LOT, increased readability & maintainability and vastly increased productivity on new dev.

3 Likes

Man, this is interesting. My team and I use Vue daily in our projects, but our Meteor project is still in Blaze. I don’t mind it much but Vue would indeed be nice, I’ve just been feeling like it would be daunting to refactor things. Which packages did you use? And would you care to share a little of how the process went? I’m intrigued by the “didn’t take that long” bit and curious about the process.

Hi @mikeTT,

To be honest, it was quite a few years ago and my app was a bit smaller back then. Also I didn’t migrate straight from Blaze to View - I went via React! I started converting from Blaze to React (with the help of viewmodel.org which makes React much nicer to use), I think so that I could use SSR. There were packages which allowed me to use React components within Blaze and vice-versa, so I was able to gradually migrate each component while the app still functioned so I was able to test each component as I went.

Then Vue came along and I fell in love, so to teach myself Vue I converted it all in one go. I don’t think I was able to mix Vue with React, but I can’t remember.

What I do remember is that once I got into the swing of converting a React (ViewModel) component to Vue it got quite repetitive and quick. Converting the jsx templates to Vue directives was fairly easy (and imo made the templates much easier to read) and then converting the javascript was mostly just copying code into different places. In the process I was able to remove a lot of boilerplate code because Vue makes things so easy.

So sorry, I can’t really answer your questions. As for packages I used, I pretty much just followed the guide and used akryum:vue-component.

2 Likes

Really appreciate this. Sounds like Blaze (which I think is quite fast and reactive) isn’t as fast as Vue. Besides maintainability and readability, that’s another compelling reason to switch to Vue.

Thanks for the reply and the links as well. Also glad to you were pleased to go from React to Vue. I don’t mean to speak poorly about React (there may be many who love it), but my team and I find Vue to be so much easier to work with. There’s seemingly needless complexity with React that doesn’t appear to make it a better alternative to Vue. Or perhaps I just haven’t found a use-case, but it’s been years of building features and Vue has never come up short.

2 Likes

That precisely sums up my own experience!

1 Like

That link should probably be viewmodel.org :slight_smile: