Angular show-hide animation always shows with reusable field directive - javascript

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.

Related

Angular with ng-flow : existing flow object

Might be a silly question but I couldn't figure the solution out myself or google it. I'm using a button for click+upload files. However, I also want to add the drag+drop functionality the same time - using preferably the same flow object and function. Here's my current code:
<div flow-init flow-name="uploader.flow" flow-files-submitted="uploadFiles()"
flow-file-success="fileUploaded()">
<label for="file-upload" class="upload">Files</label>
<input id="file-upload" type="file" flow-btn>
So I'd like to use the 'uploader.flow' scope for my drag and drop too executing 'uploadFiles()' with it on submit. Here's what I've been trying:
<div flow-init flow-object="...??..." flow-drop
flow-files-submitted="uploadFiles()" flow-file-success="fileUploaded()" ></div>
I believe myself the issue is only that I can't figure out what to put in flow-object. But I doubt it was that simple. Might be something also with the new init? Should it be done or not.
Another way around of course could be to find the first shared parent element and init it there instead for both the same time? But would this be a bit too vague?
So in the end I did what I didn't originally want to do. I went up the parent elements until I found a common one the both were children of and did the initialization for ng-flow there instead.
It works.

angularjs drag and drop html content

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
}
});
}

angularjs directive: not replace nor transclude

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>

Hide input-help on form using AngularJS

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>

how to show an empty template in custom directive

I am working on a custom directive that will show the transcluded empty template when there is nothing to show in the scope -- as in this plunker.
I could not achieve to remove the empty template in ng-repeat nor I was able to show the empty message only when there is no data. How can I display the empty template when there is nothing to show?
Actually I am not sure that it is right way to do it in directive - you'll better show different DIVs inside of your main template.
But here is my idea: instead of transclude, do manual compiling depending on is there any items to show or not.
Here is working (but still little bit dirty) plunker: http://plnkr.co/edit/dxUjpeCbSKKjaXqK9qBF?p=preview
Note, that even as I am watching whole list, re-compiling is done only when state (empty/non-empty) is changed.
Note2: It is not full transclusion - scope inside of templates (empty and not empty) will be isolated to directive's scope. You can workaround that by using different compilation or child scopes - there are couple solutions, but they are not related to this question :)
You don't need a directive for this. Just remove the directive from app.js and replace the code after buttons with this:
<div ng-hide="things.length">nothing to show here</div>
<div ng-show="things.length">
<ul>
<li ng-repeat="thing in things">thing #{{thing}}</li>
</ul>
</div>
Here's the working code: http://plnkr.co/edit/u4FF77y6dhXHj0FQC9Ai?p=preview

Categories