Angular shows only one custom element - angularjs

I try to create custom html form elements with angular.js. The idea is that I have one maintemplate for the formfield-layout and paste in the template needed for textfield, datefield or whatever.
var app = angular.module("myApp", []);
app.controller("MainCtrl", function ($scope) {
$scope.window = window;
});
// create general formfield-layout
function buildFormTemplate(innerTemplate) {
var t = '<div class="control-group">'
+ '<label class="control-label" for="{{x.id}}">{{x.label}}';
t += '<span ng-show="x.required" class="required">*</span>',
t += '</label><div class="controlls">';
t += innerTemplate;
t += '</div>';
t += '</div>';
return t;
}
app.directive("textfield", function() {
return {
restrict: "E",
scope: {},
replace: true,
template: buildFormTemplate('<input id="{{x.id}}" type="text" name="{{x.name}}" value="{{x.value}}" />'),
link: function(scope, elm, attrs) {
scope.x = attrs;
}
};
});
This code works like I expect, but if I have multiple textfield-elements only one is rendered. The other textfield-elements are gone.
<textfield id="myLabel" label="label1" name="mytext1" value="with label"/>
<textfield id="anotherOne" label="label2" name="mytext2" value=""/>
renders
<div class="control-group" id="myLabel" label="label1" name="mytext1" value="with label">
<label class="control-label ng-binding" for="myLabel">
label1<span ng-show="x.required" class="required" style="display: none;">*</span></label>
<div class="controlls">
<input id="myLabel" type="text" name="mytext1" value="with label">
</div>
</div>
The second textfield is gone. What am I missing?

Close the tags and it works fine
<textfield id="anotherOne" label="label2" name="mytext2" value=""></textfield>
DEMO: http://plnkr.co/edit/ky0Tpt8qudSLSGho2QAk?p=preview

Related

Angular moment picker in fancybox

When I click on datapicker (angular moment picker) after load it in inline fancybox, it output empty window.
But if I click on datapicker input directly - all works fine.
I use fancybox as directive:
.directive('fancybox', function ($compile, $http) {
return {
scope: true,
restrict: 'EA',
link: function(scope, element, attrs) {
scope.openFancybox = function (href) {
scope.curHosterUID = angular.fromJson(attrs.hoster);
//console.log(scope.chEvent);
//scope.curHosterUID = href.replace('#viewEvent', '');
console.log(scope.curHosterUID);
var template = angular.element(href);
var compiledTemplate = $compile(template);
compiledTemplate(scope);
$.fancybox.open();
$.fancybox.open({ href: href, type: 'inline' });
};
}
};
})
<div class="input-group" moment-picker="ctrl.timepicker" format="HH:mm:ss">
<span class="input-group-addon">
<i class="fa fa-clock-o"></i>
</span>
<input id="event_start" class="form-control"
placeholder="Select a time"
ng-model="ctrl.timepicker"
ng-model-options="{ updateOn: 'blur' }">
</div>
How I can force datapicker in fancybox?

angularjs datepicker not working

I'm using Angularjs. In that I'm using jquery for datepicker; but when I'm passing the selected date value it is not fetching the selected value. I need a solution for this problem.
Find below my code:
Markup
<div class="form-group">
<label for="inputPassword3" class="col-sm-3 control-label">Project Startdate</label>
<div class="col-sm-9">
<!-- <input type="text" name="prjstartdate" id="prjstartdate" class="form-control" ng-model="vm.user.prjstartdate" required />-->
<div class="container" id="sandbox-container">
<div class="input-daterange input-group" id="datepicker" name="prjstartdate" id="prjstartdate" class="form-control" ng-model="vm.prjstartdate">
<input type="text" name="prjstartdate" id="prjstartdate" class="form-control" ng-model="vm.prjstartdate" required />
</div>
</div>
<span ng-show="form.password.$dirty && form.password.$error.required" class="help-block">Password is required</span>
</div>
</div>
Function:
function MyCntrlsave($scope,$http) {
$scope.savedetails = function() {
var vm = this;
var projectname = $scope.vm.prjname;
var cilentname = $scope.vm.clientname;
var clientstatus = $scope.vm.prjsta;
var prjstartdate = $scope.vm.prjstartdate;
var prjenddate = $scope.vm.prjenddate;
var prjurl = $scope.vm.prjurl;
alert("projectname"+projectname);
alert("cilentname"+cilentname);
alert("prjstartdate"+prjstartdate);
};
};
HTML
<input type="text" name="prjstartdate" id="prjstartdate" class="form-control" ng-model="prjstartdate" required jqdatepicker/>
In controller
var prjstartdate = $scope.prjstartdate
Use jQuery UI and add a directive
datePicker.directive('jqdatepicker', function () {
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, element, attrs, ngModelCtrl) {
element.datepicker({
dateFormat: 'dd/mm/yy',
onSelect: function (date) {
scope.prjstartdate = date;
scope.$apply();
}
});
}
};
});
Demo Here

angularjs ng-form inside directive

i have a custom form directive which creates an ng-form inside it. i want to use this form in the transcluded elements, to disable buttons etc, but its not working.. PLUNKER LINK
app.directive("myform", function(){
var templateFn = function(tElement, tAttrs){
var html = '<div ng-form="' + tAttrs.name + '">'
html += '<div ng-transclude=""></div>'
html += '</div>'
return html;
};
return {
restrict: 'E',
template: templateFn,
scope: {list: '='},
transclude: true
}
});
this is how i am using it
<myform name="example">
<input type="text" required ng-model="name2"/>
<button ng-disabled="example.$invalid"> button </button>
</myform>
do i need to compile the template during link?? i thought as the template is used and the linking is happening latter, the $compile would be taking care of that..
the generated html is as expected, except that button is not disabled
<myform name="example" class="ng-isolate-scope">
<div ng-form="example" class="ng-pristine ng-invalid ng-invalid-required">
<div ng-transclude="">
<input type="text" required="" ng-model="name2" class="ng-scope ng-pristine ng-invalid ng-invalid-required">
<button ng-disabled="example.$invalid" class="ng-scope"> button </button>
</div>
</div>
</myform>
When you transclude the contents, have it link to the same isolated scope as ng-form (instead of the parent scope which is the default):
app.directive("myform", function(){
var templateFn = function(tElement, tAttrs){
var html = '<div ng-form="' + tAttrs.name + '">'
html += '<div></div>'
html += '</div>'
return html;
};
return {
restrict: 'E',
template: templateFn,
scope: {list: '='},
transclude: true,
link:function(scope, element, attr, ctrl, transcludeFn) {
var e = element.find('div');
transcludeFn(scope, function(clone) {
angular.element(e[1]).append(clone);
});
}
}
});
Demo Plunker

How to get the name of model passed into the function in AngularJS?

I have a scenario where i need to know the value and name of model passed in to the function.
I tried the following
$scope.rad='fff';
app.directive('kmRadio', function() {
return{
restrict:'E',
compile: function(element,attrs)
{
var model = {l:''};
model.l = attrs.kmModel;
var str1="n in ";
var str2=attrs.kmOption;
var repeat=str1.concat(str2);
var htmlText='<div><div ng-switch on="format">'+
'<div ng-switch-when="kmForm">'+
'<div>'+
'<div class="floatLeft">'+
''+attrs.title+''+
'</div>'+
'<ul>'+
'<li class="rowlist" ng-repeat="'+repeat+'"> {{n}}<input type="radio" ng-model="'+attrs.kmModel+'" name="a" ng-click="radioValueChanged(n,'+attrs.kmModel+')"/></option>'+
'</ul>'+
'{{'+attrs.kmModel+'}}'+
''+attrs.kmModel+''+
''+model.l+''+
'</div>'+
'</div>'+
'<div ng-switch-when="kmPreview">'+
'<div>'+attrs.title+'<input type="radio" ng-model="'+attrs.kmModel+'" disabled="true"/></div>'+
'</div>'+
'</div></div>';
element.replaceWith(htmlText);
}
}
})
The following code is responsible for calling the function
'<li class="rowlist" ng-repeat="'+repeat+'"> {{n}}<input type="radio" ng-model="'+attrs.kmModel+'" name="a" ng-click="radioValueChanged(n,'+attrs.kmModel+')"/></option>'+
$scope.radioValueChanged = function (value,model) {
//alert("Changed value"+value + model);
alert(value +" and " + model);
//alert("model "+ model );
}
In HTML , i have a code like below
<km-radio km-model="rad" title="Gender" km-option="['De','CM','PM']"></km-radio>
When i tap on radio button in html, i am getting the o/p De and fff, but what i need is o/p De and rad
See the plunker code and check the directive kmRadio
I rewrote your directive to get the binding from the attributes parameter of the link function:
app.directive('kmRadio', function($parse) {
return {
restrict: 'E',
replace: true,
templateUrl: 'kmRadio.html',
scope: true,
link: function(scope, element, attr) {
scope.kmModel = scope.$eval(attr.kmModel);
scope.binding = attr.kmModel;
scope.title = attr.title;
scope.kmOption = scope.$eval(attr.kmOption);
}
}
})
where kmRadio.html is:
<div>
<div ng-switch on="format">
<div ng-switch-when="kmForm">
<div>
<div class="floatLeft">{{title}}</div>
<ul>
<li class="rowlist" ng-repeat="n in kmOption">
{{n}} <input type="radio" ng-model="$parent.kmModel" ng-click="radioValueChanged(n, binding)" ng-value="n"/>
</li>
</ul>
bound to: {{binding}}, value: {{kmModel}}
</div>
</div>
<div ng-switch-when="kmPreview">
<div>{{title}}
<input type="radio" ng-model="kmModel" disabled="true" />
</div>
</div>
</div>
</div>
Here is a working demo: http://plnkr.co/edit/2q8a8B4zNGpQ0C5V1x8D?p=preview

AngularJS Directive for twitter bootstrap form-group

I've been playing with angular lately, so far so good, but im struggling with directives.
I'm trying to create a directive that generates the html mark up for a standard bootstrap form group with its corresponding validation messages.
So basically I'm trying to convert this:
<form-group label="Password">
<input type="password" data-ng-model="vm.password" name="password" id="password" class="form-control form-control-validate"
required data-ng-minlength="6"
data-required-error="Password is required" data-minlength-error="Your password must have at least 6 characters" />
</form-group>
into this:
<div class="form-group" data-ng-class="{'has-error': invalid}">
<label for="password" class="col-md-2 control-label">Password</label>
<div class="col-md-10">
<input data-ng-model="vm.password" type="password" id="password" name="password" class="form-control"
required data-ng-minlength="6"/>
<div data-ng-show="changePasswordForm.$dirty && changePasswordForm.oldPassword.$invalid">
<label data-ng-show="changePasswordForm.oldPassword.$error.required" class="label label-danger">
Password is required
<br />
</label>
<label data-ng-show="changePasswordForm.oldPassword.$error.minlength" class="label label-danger">
Your password must have at least 6 characters
</label>
</div>
</div>
</div>
So far this is what I have:
app.directive('formGroup', function () {
return {
templateUrl: 'app/directives/formGroup.html',
restrict: 'E',
replace: true,
transclude: true,
require: "^form",
scope: {
label: "#",
},
link: function (scope, element, attrs, formController) {
var input = element.find(":input");
var id = input.attr("id");
scope.for = id;
var inputName = input.attr("name");
// Build the scope expression that contains the validation status.
// e.g. "form.example.$invalid"
var inputInvalid = [formController.$name, inputName, "$invalid"].join(".");
scope.$parent.$watch(inputInvalid, function (invalid) {
scope.invalid = invalid;
});
}
};
});
formGroup.html:
<div class="form-group" ng-class="{ 'has-error': invalid }">
<label class="col-md-2 control-label" for="{{for}}">{{label}}</label>
<div class="col-md-10">
<div data-ng-transclude=""></div>
</div>
</div>
This sets correctly the bootstrap class "has-error" to the form-group if the input is invalid.
Now I want to add validation messages, and I couldn't find a way that works. This is what I have:
app.directive('formControlValidate', function () {
return {
templateUrl: "app/directives/formControlValidate.html",
restrict: 'C',
require: ["^form", "ngModel"],
scope: { },
transclude: true,
//replace: true,
link: function (scope, element, attrs, controls) {
var form = controls[0];
var inputName = attrs.name;
var inputErrors = [form.$name, inputName, "$error"].join(".");
scope.$parent.$watch(inputErrors, function (newValue) {
if (newValue) {
scope.errors = [];
angular.forEach(newValue, function (value, key) {
var error = attrs[key + 'Error'];
if (value && error) {
scope.errors.push(error);
}
});
}
}, true);
}
};
formControlValidate.html:
<div class="controls" ng-transclude></div>
<div data-ng-repeat="error in errors">
<div class="label label-danger">
{{error}}
</div>
</div>
But this doesn't work. I'm randomly changing parameters in both directives but can't figure out what how to make it work.
Any ideas or improvements would be greatly appreciated.
Thanks!
UPDATE: this is my latest gist (angular 1.3): https://gist.github.com/lpsBetty/3259e966947809465cbe
OLD solution:
I tried something similiar, maybe this link can help you too: http://kazimanzurrashid.com/posts/create-angularjs-directives-to-remove-duplicate-codes-in-form
This was my solution. I don't know why but I had to use form.$dirty, it was not possible to use input.$dirty..
(and I use angular-translate)
HTML:
<form-group input="form.password">
<input type="password" class="form-control" placeholder="{{ 'user.password' | translate }}" required
name="password" ng-model="user.password" />
</form-group>
Directive:
app.directive('formGroup', function ($parse) {
return {
restrict: 'E',
require: '^form',
transclude: true,
replace: true,
scope: {
cssClass: '#class',
input: '='
},
template: '<div class="form-group" ng-class="{\'has-error\':hasError, cssClass:true}">'+
'<div ng-transclude></div>' +
'<div ng-show="hasError">' +
'<span ng-repeat="(key,error) in input.$error" class="help-block"' +
'ng-show="input.$error[key]">{{\'form.invalid.\'+key | translate}}</span>' +
'</div>' +
'</div>',
link: function (scope, element, attrs, ctrl) {
var form = ctrl;
var input = attrs.input;
scope.$parent.$watch(input+'.$invalid', function (hasError) {
scope.hasError = hasError && form.$dirty;
});
}
};
});

Resources