Call function when control is shown - html

I have input control:
<input id="someID" class="form-control" type="text" name="SomeData"
data-ng-model="vm.SomeData">
and I need to initialize value vm.SomeData when user will scroll down to this control. I am new in angular, so not sure is there some event like 'ControlDisplayed'?

//html
<input id="someID" when-scrolled="vm" class="form-control" type="text" name="SomeData" data-ng-model="vm.SomeData">
//try this directive
app.directive("whenScrolled", function(){
return {
restrict: 'A',
link: function(scope, elem, attrs){
// we get a list of elements of size 1 and need the first element
raw = elem[0];
// we load more elements when scrolled past a limit
elem.bind("scroll", function(){
if(raw.scrollTop+raw.offsetHeight+5 >= raw.scrollHeight){
scope.vm.name = 'Nainish Modi';
// we can give any function which loads more elements into the list
scope.$apply(attrs.whenScrolled);
}
});
}
}
});

Related

Jquery validate error messages not showing up

i have an array of inputs generated upon a press of a button. the index is maintained using a global variable numInput set to 0. This is the first HTML of the input.
<label><span>First name</span>
<input placeholder="First name" type="text" name="fName[0]" id="fName"></label>
This is the addmore button, which increments numInput and appends the new and mostly the same HMTL with different index
$(document).on('click','#addmore',function(){
numInput++;
var html = '<label><span>First name</span>
<input placeholder="First name" type="text" name="fName['+numInput+']" id="fName"></label>';
$("#frm").append(html);
rerunRules();
});
Here is my validate method. I did not create the message object here...
$(document).ready(function() {
$('#frm').validate({
highlight: function(element, errorClass) {
$(element).fadeOut(function() {
$(element).fadeIn();
});
},
errorPlacement: function(error, element) {
error.appendTo(element.prev("span"));
},
});
});
rerunRules();
instead I changed the defaults:
<script>
jQuery.extend(jQuery.validator.messages, {
required: "- This field is required."
});
</script>
The rerunRules() is a function that I had to call to "reinject" the rules everytime a new HTML is generated. It is also called right after validate() because the fName rules are in it.
function rerunRules(){
$.each( $('input[name^="fName"]'), function () {
$(this).rules('add', {
required: true
})
});
}
Contrary to what I expected, the error message appears on the first fName[0] just as where its meant to be (to the previous span) but doesnt appear on the next generated HTML from the button. The validate works (wont proceed when I dont enter proper data), the highlight works, but no error message.

show the list of files selected from different directories and ability to remove the files

I am trying to attach some files (zero/single/multiple) and send them as attachments to an email using ANGULARJS and spring.
One thing noticed is when selecting the files from multiple directories only the recently selected file is shown and previous selected file is not shown. How can I show all the files selected by the user from different directories too and give the ability to delete the file (all files or one file) before submitting the form.
Demo:http://plnkr.co/edit/M3f0TxHNozRxFEnrqyiF?p=preview
html:
<body ng-controller="MainCtrl">
<p>Hello {{name}}!</p>
TO: <input type="text" name="to" id="to" ng-model="to" required ></input><br>
Subject : <input type="text" name="subject" id="subject" ng-model="subject"></input>
<br>Attachment: <input type="file" ng-file-model="files" multiple /> <br>
<p ng-repeat="file in files">
{{file.name}}
</p>
<textarea rows="20" maxlength=35000 name="message" ng-model="message" ></textarea>
<button type="button" ng-click="upload()">Send</button>
</body>
js:
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
$scope.files = [];
$scope.upload=function(){
alert($scope.files.length+" files selected ... Write your Code to send the mail");
};
});
app.directive('ngFileModel', ['$parse', function ($parse) {
return {
restrict: 'A',
link: function (scope, element, attrs) {
var model = $parse(attrs.ngFileModel);
var isMultiple = attrs.multiple;
var modelSetter = model.assign;
element.bind('change', function () {
var values = [];
angular.forEach(element[0].files, function (item) {
var value = {
// File Name
name: item.name,
//File Size
size: item.size,
//File URL to view
url: URL.createObjectURL(item),
// File Input Value
_file: item
};
values.push(value);
});
scope.$apply(function () {
if (isMultiple) {
modelSetter(scope, values);
} else {
modelSetter(scope, values[0]);
}
});
});
}
};
}]);
The default browser behavior is showing currently selected files, to cahnge that you've to customize that filed. And also, I saw your custom directive code, it doesn't allow to select multiple files from different directories.
So, what you can do is, create another scope variable & every time user selects file/files you push those files to this array. In this way you've have set of all selected files from same/different directories and then you can have delete functionality over each file which's ultimately going to be updated.
Updated html view part:
Attachment: <input type="file" ng-file-model="files" multiple /><br>
<p ng-repeat="file in filesToUpload track by $index">
{{file.name}} <span class="delete-file" ng-click="deleteFile($index)">X</span>
</p>
And for this new array update directive scope.$apply part as:
scope.$apply(function () {
if (isMultiple) {
modelSetter(scope, values);
} else {
modelSetter(scope, values[0]);
}
if(values){
scope.filesToUpload = scope.filesToUpload.concat(values);
}
});
In controller have deleteFile function as:
$scope.deleteFile = function(index){
$scope.filesToUpload.splice(index, 1);
};
Working Demo Example
Now user'll be able to delete files anytime. But the input field will still show the last selected file/files and after deleting particular file also it'll not change its status so for that you can just hide field by opacity: 0; css & then create customized Upload button & from that trigger click on actual hidden file input element.
Update: Check this update of same code with custom upload button:
Plunker Example

adding element to parent from directive

In order to disable the auto complete of chrome in forms, i want to create angular directive which add dummy input element
my code is
`angular.module("noc.components").directive('customInput', function ($compile) {
"use strict";
return {
restrict:'E',
template:'<input>',
replace:true,
link: function(scope, elem) {
//scope.type = attrs.type || 'email';
var el = angular.element('<input name={{type}} style="display: none">');
//var type = elem[0].name;
$compile(el)(scope);
elem.parent().append(el);
}
};
});`
and the html is
<div class="form-group">
<label for="setupWizardUserStepEmail">Email Address</label>
<custom-input class="form-control"
id="setupWizardUserStepEmail"
ng-model="setupRequest.userRequest.email"
name="email"
ng-required="true"
noc-validation="email"
autocomplete="off"
autofocus="true">
</div>
however the injected html isnt in the parent - i want it to be above the directive
how can i do it?
I was able to solve my own problem in the end:
I changed it to elem.parent().prepend(el);

Need to execute some code when nested ng-if in my custom directive ends compilation and recreates element

Have simple directive
.directive('test', function () {
return {
templateUrl: 'dir.html',
scope: {
date: '='
},
link: function (scope, element, attrs) {
element.find('.date-picker').attr('type', 'email');
}
};
});
And simple template for directive
<div ng-if="date">
<h1>Date is true</h1>
<input class="date date-picker" type="text"/>
</div>
<div ng-if="!date">
<h1>Date is false</h1>
</div>
I want to do smth with child element inside any div with ng-if.
My code https://plnkr.co/edit/ewHfBj6SjCss1cs4CsY7?p=preview
You can add an watch to the date and then execute the code you want to run when it changes.
scope.$watch('date', function(dateValue){
if(dateValue){
//Code to run if true
}else{
// code to run if false
}
});

How to convert text to uppercase while typing in input field using angular js

I know that is posible with jquery but I dont know how to do that with angular js, please any sugestion?
function mayuscula(campo){
$(campo).keyup(function() {
$(this).val($(this).val().toUpperCase());
});
}
You can also create a directive for this!
Check the code:
directive('uppercase', function() {
return {
restrict: "A"
require: "?ngModel",
link: function(scope, element, attrs, ngModel) {
//This part of the code manipulates the model
ngModel.$parsers.push(function(input) {
return input ? input.toUpperCase() : "";
});
//This part of the code manipulates the viewvalue of the element
element.css("text-transform","uppercase");
}
};
})
For its usage, here's an example:
<input type="text" ng-model="myModel" uppercase />
You could do it in HTML template or via JS using the angular uppercase filter.
<div>
<label>Input 1</label>
<input type="text" ng-model="first">{{ first | uppercase }}
</div>
If you need to change the value in-place, use toUpperCase when ever value is changed.
<div>
<label>Input 1</label>
<input type="text" ng-model="first" ng-change="text = text.toUpperCase()">
</div>
Above in preferred approaches. Here's yet another way to achieve same result using $watch but this is not recommended. See comments section.
<div>
<label>Input 2</label>
<input type="text" ng-model="second">
</div>
var unwatch = $scope.$watch('second', function(val) {
$scope.second = $filter('uppercase')(val);
}, true);
$scope.$on('$destroy', unwatch);
Related Plunker here http://plnkr.co/edit/susiRn