1

I'm new to Angular and trying to figure out how to watch for a title to be entered in an input so that I can use the value for a url slug.

I am trying to create a custom directive, but am unsure how to watch for when the title field has input.

HTML

<input ng-model="post.title" type="text" class="form-control"></br>
<slug></slug>

Slug directive

Posts.directive('slug', function() {
    return {
        restrict: 'E',
        scope: {},
        link: function(scope, element, attrs) {
            scope.$watch('post.title', function() {
                console.log('title has been entered');
            });
        }
    }
});

This returns 'title has been entered' immediately in the console log after refreshing the page, which isn't what I want.

Also, I don't want to completely bind the title and slug as one model, I want to capture the value that is initially typed into the title field and then use it as the slug, but allow the slug to be edited as its own model value.

Thanks for any advice, I've been stuck on this for awhile.

4
  • I think you want a custom filter docs.angularjs.org/guide/filter Commented Jun 12, 2014 at 23:19
  • 1
    No It's not the output of the data that I am confused about, I know how to lowercase and remove spaces, its capturing the title input and making that captured value editable that I am confused about.. Commented Jun 12, 2014 at 23:24
  • Sorry, missed that last part about editing the slug. That's going to be a frustrating UI. What happens if they edit the title after editing the slug? Commented Jun 12, 2014 at 23:30
  • What do you mean by initially typed? How do you know when they are done typing the title? Commented Jun 12, 2014 at 23:32

2 Answers 2

2

Your scope.$watch('post.title', ... ) is not working because you created an isolated scope for directive, and it has no access to scope with post.

About directive - it would be something like:

HTML

<input type="text" ng-model="name"/>
<input type="text" ng-model="slug" slug="name"/>

JS

.directive('slug', function () {
    return {
      restrict: 'A',
      scope: {
        slug: '=',
        ngModel: '='
      },

      link: function (scope) {
        scope.$watch('slug', function (newValue, oldValue) {
          var trExp = /[\/\s]+/gi;
          oldValue = (oldValue || '').replace(trExp, '-');
          newValue = (newValue || '').replace(trExp, '-');
          if (scope.ngModel === oldValue || !scope.ngModel) {
            scope.ngModel = newValue;
          }
        });
      }
    };
  });

http://plnkr.co/edit/GPx9uvz84F9DJTSb49c7

Also there is a check: if previous slug value was auto-generated(if not - if will not be updated).

Another thing that you will probably need is - slug validation, for this:

  1. require ng-model controller
  2. add watch for slug value with validation logic, that will call $setValidity on model controller.
Sign up to request clarification or add additional context in comments.

2 Comments

This isn't what i'm looking for, I don't want the slug and title bound together, I just want to grab the initial values in the title field and turn that into the slug model, then allow that value to be edited and not connected to the title
@MitchGlenn if I understand what you want to achive - replace content of link with something like: scope.ngModel = scope.slug.replace(/[\/\s]+/gi)
1

I was also looking for slug generator. And this is what I wanted. Take a look. http://paulsmith.github.io/angular-slugify/

Comments

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.