I'm currently learning AngularJS and i would like to accomplish a simple task.
On a form input, i would like to hide corresponding 'input-help' even data entered in input is invalid.
The way i'm currently doing this invoke some jquery. But i'm searching the way to do it using AngularJS logic. I think i should use directive but as i'm new to angular, i don't know exactly how to do it.
Here is the jsFiddle sample code working using jquery: JSFIDDLE
And here is the jsFiddle sample code not working (no jquery): JSFIDDLE
{For test, enter just few text in password input and blur it}
This is the code i have: {jquery}
$(document).on('blur', '.immediate-help', function () {
$(this).next('.input-help').fadeOut();
}).on('focus', '.immediate-help', function () {
$(this).next('.input-help').fadeIn();
});
This works as expected but i would like to use angular directive to do it. Of course, i'm not against using jquery in angular directive.
So, to resume, i would like when blur input is triggered to hide 'input-help' even the text is not valid and using angular directive.
Could someone show me the right way to do it?
Several approaches:
Using script in directive:
elm argument within directive link callback is a jQuery object if jQuery.js loads before anugular.js in page... or it is a jQlite if jQuery.js not included.
jQlite has many of the most common jQuery methods so you can use :
elm.bind('blur....
See angular.element docs for list of jQlite methods.
Using ng-class
Give form and controls a name. This creates an object formName with properties represented by field names. You can then use angular expressions for classes, or properties like disabled within markup
<form name="myForm">
<input name="passord"/>
<div ng-class="{ShowMeClassName: myForm.password.$invalid}"> Error content</div>
</form>
ng-class will toggle the class ShowMeClassName depending on validity of field named password within form named myForm
You can use Angular-ui.
Angular-UI provides a bunch of directives, which can help you. You have the ui-event directive.
For example you can use
<input ui-event="{ blur : 'blurCallback()' }">
...
<script>
$scope.blurCallback = function() {
alert('Goodbye');
};
</script>
Related
I'm trying to make a custom widget on Thingsboard that would change the text when it's pressed. Like this:
Custom Widget creation
But it's not working at all. What am I doing wrong?
Did you read the official widgets development guide?
There are some examples that use click-events
https://thingsboard.io/docs/user-guide/contribution/widgets-development/#static-widget
Thingsboard uses AngularJS, so you can bind click-handlers to elements with the ng-click attribute like this:
<p id="text" ng-click="changeText()">Text</p>
To make this work you will need to create that click-handler in the widget's scope. The perfect place to do this is the onInit() method of the widget.
self.onInit = function() {
self.ctx.$scope.changeText = function() {
// change your text here
};
};
I have a custom directive which holds a <textarea> element along with other HTML elements in its template using templateUrl. This directive should allow a user to type with any Indian Language (using any writing script like devanagri and others). The user will get to select the input language.
This directive will be used like this in my HTML:<keybuddy></keybuddy>
Now my problem is, in my main code, how should I retrieve the text entered in the textarea that is located in the template.html specified by templateUrl? I have the text available in the scope of my link function since I used ng-model on the textarea.
<textarea id="inputField"
placeholder="start typing....."
ng-model="inputText"
rows="5">
</textarea>
In my index.html, I should be able to do something like this:
<keybuddy></keybuddy>
<button onclick="printText()">Show Text</button>
<script>
var printText = function () {
console.log($("keybuddy").value);
}
</script>
How do I do it? Is there any other better way using the power of AngularJS? I went through these posts but wasn't helpful. Or might be I could not understand how to use it in my work. How to set a native attribute from AngularJS directive?, How to get evaluated attributes inside a custom directive
my complete code on github: keybuddy
Note:
I should be able to use this directive anywhere in the application, any number of times.
It should be portable; I should be able to use it in any of my project or any other developer should be able to use it without much
Go Angular :-)
You don't need the use of jQuery here. Angular is sufficient enough. You can change your code like this:
In your View:
<keybuddy model="myInputText"></keybuddy>
<button ng-click="showText()">Show Text</button>
In your View controller:
$scope.showText = function() {
console.log($scope.myInputText);
}
And update your directive to have scope like below (replace your `scope: true):
scope: {
inputText: '=model'
}
Read more on Isolating scope of a directive
You can setup a bi-directional binding to the directive scope. This will allow your directive to change a value in the parent scope, which you can then read from your controller.
In your directives configuration setup the scope property with the name of an attribute to use for the binding, such as:
scope: {
model: '='
}
In your directive's template then you can set the textarea's ng-model to that binding name.
<textarea ng-model="model"></textarea>
In the parent where you use the directive, pass the attribute you configured set to the name of a variable on the scope.
<keybuddy model="inputText"></keybuddy>
Then in your controller you can access the textarea's current content by reading $scope.inputText.
$scope.printText = function(){
alert($scope.inputText);
}
Template:
<button ng-click="printText();">Print text</button>
Since it's already in the scope, you could simply use
console.log($("keybuddy textarea").scope().inputText);
AngularJS version:
console.log(angular.element("keybuddy textarea").scope().inputText);
EDIT: Adapted to match the actual source code.
I am working on implementing the 'Floating Label' concept. In trying to DRY up my code, I found a directive that will build up the input form HTML during the compile phase.
What is happening is that the 'Floating Label' is shown and then fades away when using the directive, but behaves properly by not having the label be shown at all in the hard-coded implementation.
Example Here:
http://plnkr.co/edit/GMZnAYlq49WoPhERRnEY?p=preview
The final HTML looks like below in both the hard-coded and directive implementation:
<div class="field">
<label ng-show="ctrl.workingField" class="show-hide">Working Field</label>
<input type="text" class="form-control" ng-model="ctrl.workingField" placeholder="Working Field"/>
</div>
If the generated HTML is the same, why is the directive flashing the 'Floating Label'? I want to use the directive but have it behave like the hard-coded solution.
Any thoughts?
As I understand that you want to meke decision using the directive or not? Because both two example work same.
The directive restricted for only element tag. It validate information and produce an html which is the same with your hard coded example. Namely, there is no other javascript action. Animations are worked via CSS.
You are not able to use the directive. Just use it's CSS. Hard coded example has more flexiable usage then the directive.
Edit
Sorry I have seen the problem that you say.
Please change the directive code line
labelElement.attr('ng-show', attrs.ngModel);
to
labelElement.attr('ng-hide', !attrs.ngModel);
and add
.show-hide {
display:none;
}
to css file.
Because ng-show try hide the label and it trigger ng-hide-add transition.
I am trying to create a live HTML editor with AngularJS, where user can drag and drop some DOM elements to a container and it will render the final HTML page, for example, there is a button (or whatever) that says "Drag me to create an input", then user will drag that item into the container and an input field will be rendered...
I've been trying ngDraggable module but isn't what I needed...
I think a way is to hold the HTML code into some $scope variable, and when the user drops the button into the container, $scope.input which contains <input type="text" placeholder="Something"/> will be rendered inside container...
My final step is to enable inline edit to thoose HTML elements generated, in order to let the user create some content agains that final template.
When the user finish, the whole HTML code will be saved somewhere or downloaded...
I don't need something complex, just a few predefined elements that can be dropped...
I hope I've explained it correctly.
There is some example found at http://nboychev.com/tests/angular/Drag%20Drop%20iFrame%20using%20Angular%20JS%20Directive.html that does exactly what I want (see source), BUT:
It's using jQueryUI (Which I don't want to use, but if its needed then I will)
It isn't working on my project. I must say that I'm using RequireJS, but everything works on my angular app but the directives mentioned on the link above. Draggable is not working, I do not have any errors and I've checked that the code is being executed, doing some console.log() stuff, but still not working...
But it contains what I want, draggable stuff with HTML injected that renders content on an iframe (or a div, or whatever) and that new content is also droppable, to insert more stuff inside that code. Give it a try, and guide me a little. Thanks
I think it's better if you try using something as jui
On the other hand you can try implementing your own directive:
<br>
<h4>Drop Area</h4>
<div droppable jui-options="{addClasses: false}" class="drop-area"></div>
<div class="read-out">
<span class="text-info"><strong>Draggable ID</strong></span>: {{obj.id}}<br><br>
<span class="text-info"><strong>Content</strong></span>: <span ng-bind-html="obj.content"></span><br><br>
<span class="text-info"><strong>Actual Content</strong></span>: {{obj.content}}<br><br>
</div>
</div>
http://codepen.io/m-e-conroy/pen/jCdhu
Sounds like a fun project.
This is a simple link function using JqueryUI and Angular. You'll need an HTML element in scope with class "draggable". Use destroy() when finished.
Adding HTML to the DOM from the scope, check out this solution by Josh David Miller: http://jsfiddle.net/paulocoelho/fBjbP/2/
Or for simple HTML elements for visual display only you could try using ngBindHtml, ngRepeat and ngSanitize. Then adding / removing HTML elements to and from an array should display them in a container.
link: function($scope, $elem, $attr){
$elem.find(".draggable").draggable({
start: function(event, ui){
$(ui.item).addClass("shadow");
},
stop: function(event, ui){
$(ui.item).removeClass("shadow");
// DO SOME ANGULAR STUFF HERE
}
});
}
I need to append a directive's template AFTER an input field. The original input field needs to remain - I can't just create a duplicate of it. My thought for this was to, in the controller, use jQuery to add a DIV after the input field, and add an attribute for the directive to the div. However, in practice, that doesn't work - the div is created and added, but the directive doesn't activate.
The problem, I know, is that the jQuery-added div is not yet recognized by the angularjs controller - it appears AFTER angularjs runs over the controlled html.
I know that part of the problem is that you're not supposed to use jQuery in the controller, but I honestly can't think of another way to do it. Is there some way to cause the angularjs controller to look at this new div?
The original HTML looks like the following.
<input name="generatedString_1234567890">
I run jquery over the page to add a controller to the body. The relevant code looks similar to this:
jQuery('body').attr('ng-controller','MainCtrl');
angular.module('app',['DataTools']);
angular.element(document).ready(function(){
angular.bootstrap(document, ['app']);
});
Inside the angularjs, I run a resource to get a json string containing the relevant changes to the DOM, in terms of attributes that need to get added to the inputs and certain understood flags that require specific coding. The relevant task I'm trying to accomplish looks like this, where $(this) is the input field for the DOM.
jQuery(document).find('input.FormField,select.FormField').each(function(){
// Inside a case statement based on certain flags
var d = $('<div/>');
d.attr("ng-model", 'adors.'+label);
// Relevant code that adds attributes to the div - including the required directives
$(this).hide().after(d);
}
I am trying to create code that looks more like this (VERY GENERIC):
<input name="generatedString_1234567890" ng-hide="true" ng-model="input.uniqueKey">
<div special-input="time" ng-model="input.uniqueKey">
<select ng-repeat="hour in hours">
<select ng-repeat="minute in minutes">
</div>