redband
redband

Reputation: 287

Expandable textarea field for chat app using angular directive

I'm using angular/bootstrap and have a particular directive which functions as the actual chat input box to my app. I've gotten the more important expanding behavior done, except I can't quite figure out how to do three things in specific...

Here is the fiddle

1) I need to have the enter key submit the text inside the textarea (using the button of the form is optional, feel free to remove it). I'm getting the following error in my console: "Uncaught ReferenceError: $ is not defined" (lack of knowledge of js structure here).

2) Since I'm using angular, where I should include the custom script? Probably not inline inside tags in the directive...maybe inside controllers.js? What's the best practice for that?

3) The ajax call inside the script this.form.sendThought();, can controllers.js be accessed from the script? I guess #2 above needs to be in a place such that I could access this function...

Here is the directive:

<div class="clear" ng-show="allowInput">
                <form role="form">
                        <div class="input-group">
                            <div class="textarea-container" id="txtCont">
                              <textarea ng-model="rawResponse"></textarea>
                              <div class="textarea-size"></div>
                            </div>
                          <span class="input-group-btn">
                            <button class="btn btn-lg" type="button" ng-click="sendThought()">send</button>
                          </span>
                        </div>
                </form>
</div>

Script:

var textContainer, textareaSize, input;
var autoSize = function () {
  textareaSize.innerHTML = input.value + '\n';
};

document.addEventListener('DOMContentLoaded', function() {
  textContainer = document.querySelector('.textarea-container');
  textareaSize = textContainer.querySelector('.textarea-size');
  input = textContainer.querySelector('textarea');

  autoSize();
  input.addEventListener('input', autoSize);
});

$('#txtCont').keydown(function() {
    if (event.keyCode == 13) {
        this.form.sendThought();
        return false;
     }
});

Upvotes: 0

Views: 1122

Answers (1)

Antiga
Antiga

Reputation: 2274

You don't have jQuery included (which is what the $ global object usually means here). You can either include jQuery or do this with vanilla JS. (Even better, use jqLite from inside the Angular directive!)

Here's what a keyup event looks like with plain JS. You don't have to name the function like I did if you prefer to pass an anonymous function in. I prefer to name them so I can modify later if I need to. (I also think it's cleaner)

document.getElementById('chat').onkeyup = keyPressedChat;

http://jsfiddle.net/k0kyu5t7/

I put that together real quick to help give you an idea about what I mean by using vanilla JS outside the context of your app.

I noticed a couple more problems looking at it a second time (besides not including jQuery):

  1. You should be listening for keydown events on the textarea element instead of the parent div. It's possible to capture keypress events that you might not want unless you point to the text area specifically.
  2. You should be passing the event into your anonymous function callback that you're attaching to the handler.

The answer to your #2 is far too broad for a quick discussion here. There are a lot of opinionated ways on how to organize your files in an Angular app. I personally like to break things down by components and then drop them inside folders like that. Your "chat-directive" could live inside [Root] -> [Chat] -> [Directives] -> chat.js. That's just one way.

As for your #3, it depends on what you want here. You can call services/factories from your directives, which is where your ajax calls should be anyway. If you want your directive to be more modular, then one option might be to pass a method through the directive itself (via the view).

Upvotes: 1

Related Questions