Skip to content

Instantly share code, notes, and snippets.

@ggoodman
Created July 24, 2012 21:57
Show Gist options
  • Save ggoodman/3172938 to your computer and use it in GitHub Desktop.
Save ggoodman/3172938 to your computer and use it in GitHub Desktop.
Reacting to additions/deletions/changes to keys and their values in Angular.js

How can I react to additions and deletions of keys in a scope object as well as to changes to sub values?

The scratch

The new version of plunker has the concept of a scratch. The scratch is the current state of the editor that can periodically be saved as a plunk. The scratch is structured as follows:

{
  files: {
    "index.html": {
      filename: "index.html",
      content: "<h1>Html goes here</h1>"
    }, /* More files... */
  }
}

The scratch is defined as a directive and so I can't seem to get access to the parent scope to broadcast events. See scratch.coffee.

Because the scratch is the authority on what is in the current edit session, it seems normal that it should generate the events that would allow other components (the ace textarea) to react to file additions/deletions/changes.

With things organized as described above, I can't figure out how to let the scratch remain the authority on edit session state while allowing it to 'notify' other components of changes to its structure.

Any ideas?

#= require ../vendor/angular
#= require ../services/modes
EditSession = require("ace/edit_session").EditSession
UndoManager = require("ace/undomanager").UndoManager
module = angular.module("plunker.ace", ["plunker.modes"])
module.directive "plunkerAce", ["modes", (modes) ->
restrict: "A"
link: ($scope, el, attrs, ngModel) ->
$scope.ace = ace.edit(el[0])
$scope.$on "layout:resize", ->
$scope.ace.resize()
addSession = (file) ->
unless file.session
session = new EditSession(file.content or "")
session.setTabSize(2)
session.setUseSoftTabs(true)
session.setUndoManager(new UndoManager())
session.setMode(modes.findByFilename(file.filename).source)
changing = false
#$scope.$watch file.content, (content) ->
# console.log "VALUE", content
# changing = true
# session.setValue(content)
# changing = false
read = -> file.content = session.getValue()
session.on 'change', -> $scope.$apply(read) unless changing
file.session = session
# If this worked, then all would be well
$scope.$watch "scratch.files", (files) ->
addSession(file) for filename, file of files
$scope.$on "scratch:add", (file) -> addSession(file)
$scope.$watch "active", (active) ->
addSession(active) unless active.session # Hack to create a session on the first activation
$scope.ace.setSession(active.session) if active.session
]
#= require ../vendor/angular
module = angular.module("plunker.scratch", ["plunker.url"])
module.factory "scratch", ["$http", "$q", "url", ($http, $q, url) ->
new class Scratch
@defaults:
description: "Untitled"
files:
"index.html":
content: """
<!doctype html>
<html>
<head>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<h1>Basic Plunk</h1>
</body>
</html>
"""
filename: "index.html"
"style.css":
content: """
/* CSS goes here */
h1 {
color: blue;
}
"""
filename: "style.css"
"script.js":
content: """
// Javascript goes here
"""
filename: "script.js"
constructor: ->
angular.copy Scratch.defaults, @
promptNewFile: (new_filename) ->
if new_filename ||= prompt("Please enter the filename")
for filename, file of @files
if file.filename == new_filename
alert("A file already exists called: '#{new_filename}'")
return
@files[new_filename] =
filename: new_filename
content: ""
]
@IgorMinar
Copy link

yes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment