How to pass variables from angular controller to jquery - javascript

I have two html divs, each having a bunch of input fields. I also have an angular controller that gets the data entered in the input fields and checks if they are valid (ie: email, passwords match, etc). What I'm trying to do is hide the first div and show the second one once the controller says that the text entered in the first div is valid. Here is what the html looks like:
<div id = "stageOne">
<!-- whole bunch of inputs here -->
</div>
<a class = "btn" id = "stageOneDone" ng-click = "checkFields(true)">Continue</a>
<!-- First stage ends here-->
<div align = "center" id = "stageTwo" style = "display: none">
<!-- whole bunch of inputs here -->
</div>
<script>
$(function(){
$('#stageOneDone').click(function(){
//var completedIncorrectly = something
if(!completedIncorrectly){
$('#stageOne').hide();
$('#stageTwo').show();
}
})
});
</script>
The function checkFields() expects the value true when it should check the values of the first div and false for the second div. What I can't figure out how to do is get the return value of the function and use it in jquery.
EDIT: If you're thinking why not just show/hide the divs using angular, I want to use jquery's animations.

Fixed this problem by just writing all the jquery in the controller.

You can set variable inside controller, like $scope.step = 'one';
<div ng-show="step='one'">first step</div>
<div ng-show="step='second'">second step</div>
...
You don't need jQuery to do this.

Related

Bootstrap select required validation not working properly

We have a bootstrap select (Phasentyp) that is added dynamically via a template.
The template looks like this:
<div class="form-group">
<div class="form-row">
<div class="col-4">
<form-group asp-for="#projektphaseTemplate.PhasenTypId" asp-horizontal="true" asp-label-suffix=" *" data-none-selected-text required></form-group>
</div>
</div>
</div>
When adding the template, the select is processed via JavaScript:
// Process the bootstrap selects
projektphase.find('select').each(function(index, element) {
const el = $(element);
// Replace name
let newName = el.attr('name').replace(/projektphaseTemplate/, `Projekt.PPMProjektPhase[${newIndex}]`);
el.attr('name', newName);
// Replace ID
let newId = $(element).attr('id').replace(/projektphaseTemplate/, `Projekt_PPMProjektPhase_${newIndex}_`);
el.attr('id', newId);
// Remove all bootstrap-select DOM Stuff for prune select-elements
el.closest('.bootstrap-select').replaceWith($(element));
// Reinitialize bootstrap-select
el.selectpicker({
noneSelectedText: ''
});
});
But unfortunately, when saving with the empty option selected, the validation doesn't work.
What is "funny" is, that when I fill out the other required fields and save again, then the validation seems to trigger but with the wrong message:
The HTML looks like this:
What am I doing wrong, that the validation isn't triggered by the first save?
Thanks in advance
You have to reapply jquery's validation to your element, after you changed the name of it.
See here: jQuery - How to dynamically add a validation rule

passing the values dynamically (eg: innerHTML) to another element as a value

I've a form with three fields, which are rendered via the jinja2 template & the fields are part of a Django ModelForm. The fields are: CharField, FileField, and Textarea.
And, I've also a textarea like <div> element which exactly works like Stackoverflow's editor, omitting some options like <code>, <image> ...
But, it's totally JavaScript based. Which when rendered on the page disabling that existing TextArea that was rendered from the ModelForm. As, I defined on the page...
<script>
$(document).ready(function () {
$('#txtArea').TxtEdtr();
});
</script>
I've mentioned both the element's IDs same, to always render the second textarea by overriding the first one. And, by hiding that element by - display: none.
And to pass the context of the 2nd created textarea to that modelform textarea, I've used:
$('.myeditor').keyup(function () {
$('#txtArea').innerHTML = $('.myeditor').html();
});
By looking at the browser console I can see that keyup is working but, the context or the 1st element isn't affected. And, as it's a required element I can't submit the form also.
For example, I want to pass that html context as a string to that ModelForm's textarea element before the form is submitted:
$('#txtEditor').innerHTML = $('.editor').html();
result to pass: "<span style=\"font-style: italic;\">hi there ...<br></span>"
which is shown to the console while I ran that code, but not able to pass.
The DOM structure:
<div class="form-group">
<!-- model form element -->
<label for="txtEditor">Body of article</label>
<textarea name="details" cols="40" rows="10"
id="txtEditor" class="form-control" required="" style="display: none;">
</textarea>
<!-- after rendering -->
<div class="row-fluid main ted">
<div id="menubar_txtEditor" class="row-fluid menu-bar">
<!-- menubuttons are displayed here -->
...
...
</div>
<div class="editor" name="details" style="overflow: auto;" contenteditable="true">
<!-- portions here dynamically added if textarea has
any content inside -->
<span style="font-style: italic;">hi there ...<br></span>
</div>
</div>
You can do something like this:
// add data to the editor
$('.editor').prepend($('#txtEditor').val());
// initialize TxtEdtr
window.quill = new Quill('.editor', {
theme: 'snow'
});
// Update the model textarea value after submit
$('form').on('submit', function() {
$('#txtEditor').val(quill.root.innerHTML);
});
Vist jsfiddle, for more.
check network on jsfiddle, it's submitting the desired data.

How to add and remove text field on click of a button in angular js

I have generated button using ng-repeat directive in angular js. Now I want to generate a textfield inside a div tag on click of that button.
Example buttons -
Example textfields added on click of it -
I am doing this using innerHTML attribute of div tag, like below -
var txt = document.getElementById("paidby").innerHTML;
document.getElementById("paidby").innerHTML=txt+ "<div class='row' style='padding:2px'><div class='col-sm-4'><input type='number' placeholder="+str+"></div></div>";
But I want to know if there is any other better way using angularJS or javascript to do the same so that if I need to remove one or all of the textfields later on, it can be done easily. By removing means deleting and NOT hiding.
(becuase if I want to remove for example textfield 'two' now, I have no idea how I remove it)
You don't want to manipulate the DOM within your controller. Often times, there are better ways to do this within the framework that Angular provides.
You can do this by having another ng-repeat which loops over an array you declare within your controller. For example:
In your view:
<section id="paidby" ng-repeat="textfield in textfields">
<div class='row' style='padding:2px'>
<div class='col-sm-4'>
<input type='number' placeholder="{{textField.str}}" ng-model="textField.value">
</div>
</div>
</section>
In your controller, within your button ng-click logic:
// To add:
$scope.textFields.push({ str: someVariable, value: someValue });
// To remove:
var index = $scope.textFields.map(function(t) { return t.value; }).indexOf(someValue);
if (index !== -1) {
$scope.textFields.splice(index, 1);
}
Try hiding the inputs to start with, then show them if the appropriate button is clicked:
<script src= "http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<div ng-app="" ng-init="array=['one','two','three','four','five']; show=[false,false,false,false,false]">
<button ng-repeat="item in array" ng-click="show[$index] = !show[$index]">{{item}}</button>
<br>
<input type="text" ng-repeat="item in array" placeholder="{{item}}" ng-if="show[$index]" />
</div>

Store data on page to variables using Javascript/JQuery

So I am trying to store data to variables on the page when a button is clicked, there are multiple buttons and it needs to store data for that specific button. Each one of these buttons is nested inside a <form onsubmit></form> all the data I need to extra is within this form in different <input> and <div> tags. So using javascript or jquery how can I select the value of a specific and tag. So when the button is clicked on it adds this product to the cart, I want to take the productNumber, price, and quantity and store them to my own variables. When the button is clicked the forum calls onsubmit="ShoppingCartAddAJAX( this ); so I want to store this data in the ShoppingCartAddAJAX function.
Here is what one of the forms on the page looks like.
<form method="post" name="addtocart-501" onsubmit="ShoppingCartAddAJAX( this ); return false;">
<input type="hidden" name="formName" value="ShoppingCartAddAJAX" />
<input type="hidden" name="productNumber" value="758201" />
<input id="qtyproduct" type="hidden" class="hiddenqty" name="dmst_Qty_2805" value="1" />
<div class="price">
<div class="pricenew singleprice">
$7.99
</div>
</div>
</a>
</div>
</div>
</li>
</form>
So I have been trying to get this data by doing something like this.
var pn = $('input[name$="productNumber"]').val();
var qty = $('input[id$="qtyproduct"]').val();
In my javascript file the function looks something like this:
function ShoppingCartAddAJAX(formElement, productNumber) {
var pn = $('formElement.input[name$="productNumber"]').val();
var aa = $('formElement[name$="productNumber"]').val();
var qty = $('input[id$="qtyproduct"]').val();
}
But with alot more code... just showing that the function is passing in formElement and a productNumber.
But this is giving me the product number and quantity of the first product on the page, I need the data for which ever button the user decides to click on and there are multiple ones on the page not just one. I hope that when the button is clicked and that function is fired there is a way to look what forum it came from and then extract that data. I would also like to be able to get the price but it is stored in <div class="pricenew singleprice"> $7.99</div>.
Any help is greatly appreciated.
You are getting the product number and quantity of the first record since you have multiple input fields in the form with the name of productNumber(according to your description). So what basically happens here is when you call $('input[name="productNumber"]').val() jquery returns you the value of the first input field. Instead of that, do something like this inside your ShoppingCartAddAJAX function.
function ShoppingCartAddAJAX(form)
{
// Find child an element inside our form with the id of "qtyproduct"
// I used "find("#qtyproduct")" method so it searches anything nested inside your specific form element
// You can use "children("#qtyproduct")" method also
var qty = $(form).find("#qtyproduct").val();
var pn = $(form).find("input[name='productNumber']").val();
var pp = $(form).find(".pricenew.singleprice").text();
}

Angularjs, checking if radio buttons in form have been selected

I'm starting with AngularJS, and I'm building a multi-step form where user has to fill different pages. When finished a page, he's allowed to press a next button and fill the following page.
For the first page, I've built in the HMTL a form (named pageOneForm), with different text input fields, marked as required, and in the relative controller I'm doing this watch:
$scope.$watch('pageOneForm.$valid', function(validity) {
ModelData.actualPageCompleted = validity;
})
And it works like a charme. My model (ModelData) is updated.
I was trying to apply the same logic to the following part of the app, the second page. Instead of input text, the user has to select two options from 2 different radio buttons groups.
So I built in the html a list of buttons via ng-repeat :
<div ng-Controller="PageTwo" ng-show='data.actualPage == 2'>
<form name="pageTwoForm">
<h3>General Information > Knowledge About </h3>
<div>
<b>User</b>
<div ng-repeat="option in userOptions">
<input type="radio" name="userGroups" ng-model="data.knowledgeAboutUser" ng-value="option.id" id="{{option.id}}" required>{{option.text}}
</div>
<div ng-repeat="option in targetGroupUserOptions">
<input type="radio" name = "targetUserGroup" ng-model="data.knowledgeAboutTargetGroup" ng-value="option.id" id="{{option.id}}" required>{{option.text}}
</div>
</div>
</form>
and I've implemented the same code as above in its controller:
$scope.$watch('pageTwoForm.$valid', function(validity) {
ModelData.actualPageCompleted = validity;
})
but apparently it doesn't work, and in my model actualPageCompleted is always true...
What am I doing wrong?
Thanks
I did my best to create a controller with some dummy data to get a fiddle working with your example code. Here is the fiddle You need to force the $digest cycle to update your form's validity state on ng-click for the radio buttons (see this SO post for more details), which is why the method
$scope.forceDigest = function(){
setTimeout(function(){ $rootScope.$$phase || $rootScope.$apply(); });
};
is necessary. Alternatively, you can get rid of the method call and uncomment the html code
<h3 ng-show="false">{{data.knowledgeAboutTargetGroup}}</h3>
<h3 ng-show="false">{{data.knowledgeAboutUser}}</h3>
in the fiddle to force the form object to update as well.
And I would make sure that ModelData.actualPageCompleted is not retaining its true value from when pageOneForm.$valid became true and it was set.
I hope that this helps!

Categories

Resources