Angular Directive - how to configure bidirectional binding with ng model

I wrote a directive for the editor (wysiwyg editor). It works after some hacks, but I would like to find the right way. The main task for me is the bi-directional binding between the ng model and the jqery redactor plugin. I listen to the keyup and command event from the wysiwyg editor and update the model. I also observe model changes outside the editor editor so that I can update the editor editor accordingly. The hard part: how to ignore the ng model change introduced by the reactor editor (from the first half of the binding)?

In the following code, he remembers the last value that the editor of editors updates to the model and ignores the change of the model if the new value of the model is equal to this last value. I'm really not sure if this is the right way to achieve this. It seems to me that this is a common bi-directional binding problem in Angular and should be right . Thank!

<textarea ui-redactor='{minHeight: 500}' ng-model='content'></textarea>

directive.coffee (sorry for the coffee text)

angular.module("ui.directives").directive "uiRedactor", ->

  require: "ngModel"
  link: (scope, elm, attrs, ngModel) ->
    redactor = null
    updatedVal = null

    updateModel = ->
      ngModel.$setViewValue updatedVal = elm.val()
      scope.$apply()

    options =
      execCommandCallback: updateModel
      keydownCallback: updateModel
      keyupCallback: updateModel

    optionsInAttr = if attrs.uiRedactor then scope.$eval(attrs.uiRedactor) else {}

    angular.extend options, optionsInAttr

    setTimeout ->
      redactor = elm.redactor options

    #watch external model change
    scope.$watch attrs.ngModel, (newVal) ->
      if redactor? and updatedVal isnt newVal
        redactor.setCode(ngModel.$viewValue or '')
        updatedVal = newVal
+5
source share
1 answer

Mark Rycock made a decision (thanks!). The trick is to use ngModel. $ render (), not $ watch ().

using

ngModel.$render = ->
  redactor?.setCode(ngModel.$viewValue or '')

instead

scope.$watch attrs.ngModel, (newVal) ->
  if redactor? and updatedVal isnt newVal
    redactor.setCode(ngModel.$viewValue or '')
    updatedVal = newVal
0
source

All Articles