angularjs directive: not replace nor transclude - javascript

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>

Related

Using multiple directives with one main directive

Currently, angular-redactor.js from https://github.com/TylerGarlick/angular-redactor is being used in our application. The goal is to create a new angular directive that can handle any text editor, not just redactor.
Is there a way to call angular-redactor directive used in that approach with another, new parent directive that can display the exact same thing or based on the configuration and different text editor directive.
Functionally in the HTML it looks like this right now:
<textarea
id="title-input"
ng-model="title"
ng-disabled="!hasPermission('editPageTitle')"
height="26px"
style="resize:none; max-height: 32px"
redactor="{ buttonsHide: ['link', 'super-script', 'subscript', 'symbol']}">
</textarea>
The goal would be to have it look like this:
<my-custom-directive
id="title-input6"
ng-model="title"
ng-disabled="!hasPermission('editPageTitle')"
editor-config="fullToolbar"
editor-type="redactor">
</my-custom-directive>
Where, the directive should handle things in a way that it converts it back into the first one to be rendered by the browser. If editor-type is changed it should point to that directive and render that text editor.
One approach is to use the function version of the template property of the DDO.
template
HTML markup that may:
Replace the contents of the directive's element (default).
Value may be:
A function which takes two arguments tElement and tAttrs (described in the compile function api below) and returns a string value.
— AngularJS Comprehensive Directive API - template

Javascript variables not updated after Angularjs ng-repeat changes made to DOM

I have an angular app which extracts data from a JSON file which populates the webpage via directive template for the user using ng-repeat.
When the page is initially loaded, the ID(from the json file) in (p) element is 1.
<p id="pollidholder" style ="display:none" ng-bind-html="item.id">{{item.id}}</p>
Once the user presses a button(Next, ng-click), the ID is updated 2 in the <p> element via a directive template. I am using the ID to register the users input.
In my back end Javascript (uservotedd.js), I am using
var pollidholder1 = document.getElementById('pollidholder').innerHTML;
to extract the ID from the <p> element.
However, the ID is not updated from 1 to 2 for the var pollidholder even though the <p> element is changed on the page itself.
How do I update my Javascript variable once the html <p> element has changed? Please help. I would like avoid major rewrite of my code. Note the Alert message is not update to reflect the change in ID when the user hits the submit button.
Please find the plunker example here https://embed.plnkr.co/3kIxhW2Iq5lKQm81csln/
Just don't use onclick in your html here:
<div class="simple-button" onlclick="idchange()" ng-click="change()" style ="font-size: 4vw ">Next</div>
Put all the code of idchange into the change function of the controller, and you will have access to all the variables you need. For example:
$scope.change = function() {
$scope.indexToShow = ($scope.indexToShow + 1) % $scope.items.length;
alert($scope.items[$scope.indexToShow].id);
}
Don't try to dodge angular's encapsulation, using onclick rather than ng-click will cause lots of confusion for beginners. Just use ng-click and you will be fine.

angularJS executing directive in memory and geting innerHTML

I have created a directive in angularJS as <print-note print-data='printData' id='notePrintDiv'></print-note> this directive will take some object and create a formatted html for printing, but I don't want to show the formatted html in my main html I want the formatted html for printout. so I was hopping if there is any way in angularJS where in I just create the element and pass the scope object to it like angular.element("<print-note print-data='printData' id='notePrintDiv'></print-note>"); or any other way and get its innerHTML.
P.S. I can also achieve the same with making outer html of directive template as display: none but that seems to be a bit hacky way.
The $compile service should be able to do this. Inject it in your controller where you have access to the scope (with printData).
var element = $compile('<print-note print-data="printData" id="notePrintDiv"></print-note>')($scope);
I had to achieve samething in a AngularJS app - I kept the directive for Print-Button and I kept id for the div or HTML block that was targeted to be printed and kept that div/html ng-show=false. I think it's one of the right way to get the required task done.

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

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>

Categories