Skip to content

Instantly share code, notes, and snippets.

@Deepwalker
Created February 1, 2014 16:43
Show Gist options
  • Save Deepwalker/8754896 to your computer and use it in GitHub Desktop.
Save Deepwalker/8754896 to your computer and use it in GitHub Desktop.
Angular directives with support for forms with nested attributes
/*
clForm and clFormInput working together.
With clForm you define context and with clFormInput
you customize simple form controls.
clForm could be nested.
Sample:
<form cl-form="package as packageForm" cl-form-prefix="delivery[legs_attributes][0][package_attributes]">
<input cl-form-input="system_of_measurement" ng-model="package.system_of_measurement">
<div ng-repeat="unit for unit in package.handling_unit_attributes" cl-form="handling_unit_attributes as unitForm from packageForm">
</div>
</form>
*/
CLModule.directive('clForm', function() {
return {
restrict: 'A',
scope: true,
link: function($scope, element, attributes) {
var form = {},
prefix = $scope.$eval(attributes.clFormPrefix) || attributes.clFormPrefix || '',
match = attributes.clForm.match(/^(\w+)( as (\w+))?( from (\w+))?$/)
if (!match) {
throw 'Bad expression for clForm element'
}
var objectName = match[1],
customFormName = match[3],
fromForm = match[5]
form.objectName = objectName
if (fromForm) {
$scope.$watch(fromForm, function(parentForm) {
var objectByKey = parentForm.object[objectName],
isArray = angular.isArray(objectByKey)
prefix = parentForm.prefix + '[' + objectName + ']'
if (isArray) {
form.object = objectByKey[$scope.$index]
form.isArray = true
form.index = $scope.$index
prefix += '[' + form.index + ']'
} else {
form.object = objectByKey
}
form.prefix = prefix
})
} else {
form.object = $scope.$eval(objectName)
}
form.prefix = prefix
if (customFormName) $scope[customFormName] = form
$scope.clForm = form
}
}
})
CLModule.directive('clFormInput', function() {
return {
restrict: 'A',
link: function($scope, element, attributes) {
var match = attributes.clFormInput.match(/(\w+)( for (\w+))?/),
attributeName = match[1],
formName = match[3] || 'clForm';
$scope.$watch(formName, function (form) {
var name = form.prefix + '[' + attributeName + ']',
id = name.replace(/\]\[/g, '_').replace(/\[/, '_').replace(/\]/, '')
attributes.$set('id', id)
attributes.$set('name', name)
}, true)
}
}
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment