I'm practicing angularjs by creating a simple inventory app. I have a button to add a new product to the list of products, and I have an edit button for the existing products.
Both buttons bring up the same modal windows, and I have it set so that the title of the modal says "New Product" when I click on "Add New Product" button, and "Edit Product" when I click to edit an existing product.
The issue I'm having is when I click to add a new product the title displays correctly; however, as soon as I start typing the new code for the new product, the title changes automatically to "Edit Product".
Below is the code I'm using for this, and the entire code can be found here http://codepen.io/andresq820/pen/LWGKXW
The modal windows is not coming up in codepen.io; however, I'm writing logging "edit" to the console when the edit button is clicked, and "new" when the new product is clicked.
HTML CODE
<div class="modal fade" id="editItemModal" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">{{title(item.code)}}</h4>
</div>
<div class="modal-body">
<form name="myEditForm" ng-submit="editProduct(item)">
<div class="form-group">
<label for="code">Code:</label>
<input type="text" size="5" maxlength="5" class="form-control" name="code" id="code"
ng-model="item.code" ng-disabled="false">
</div>
<div class="form-group">
<label for="description">Description:</label>
<input type="text" class="form-control" id="description" ng-model="item.description" required>
<span ng-show="myEditForm.description.$touched && myEditForm.description.$invalid">The description is required.</span>
</div>
<div class="form-group">
<label for="amount">Amount:</label>
<input type="number" min="0" max="99999" size="5" maxlength="5" class="form-control" name="amount" id="amount"
ng-model="item.amount" integer>
</div>
<div class="form-group">
<label for="radio">Type:</label>
<div class="radio">
<label><input type="radio" name="optradio" ng-model="item.type" value="in">In</label>
<label><input type="radio" name="optradio" ng-model="item.type" value="out">Out</label>
</div>
</div>
<div class="modal-footer">
<input type="button" class="btn btn-default" data-dismiss="modal" ng-click="close()" value="Close" />
<input type="submit" class="btn btn-primary pull-right" value="Submit" />
</div>
</form>
</div>
</div>
</div>
</div>
ANGULARJS CODE
$scope.title = function(code){
console.log(code);
if (typeof code == 'undefined'){
console.log('new');
return 'New Product';
}
console.log('edit');
return 'Edit Product';
};
Change your function with below code. It will check if the code is already exist in your $scope.items or not. It will return as new if item not exited.
$scope.title = function(code){
var title = 'New Product';
angular.forEach($scope.items, function(value, key) {
var arr = Object.values(value);
if(arr.indexOf(code) !== -1 ) {
title = 'Edit Product';
}
});
console.log(title);
return title;
};
The input box for Code is bound to item.code value. As soon as you start typing anything in there, item.code is no longer undefined. And as per your condition in the method call for function, it returns Edit title when code is not undefined.
In your view you get your title through the title() function and what that function returns is based on the current code. As soon as you change anything in your model, Angular will detect a change and will go through ALL your two-way bindings and see if they need to be changed.
So in your case the following happens:
You enter a code
Angular detects a change
Angular will check all your bindings to see if they changed (ngBinding or the more common {{}})
The title() function gets called to see if it has changed, the title function has changed indeed, there is now a code so it will return the new title.
So how do you fix it? Easy!
instead of a two-way binding ({{}}) you can use a one-time binding ({{::}}). A one-time binding gets set once and then Angular 'forgets' about it, it simply won't care about any changes that happens to it any more.
In your case:
{{title(item.code)}}
to
{{::title(item.code)}}
Related
I have a modal for creating new post. I want to allow the user to select departments for sharing so I'm using checkboxes for choosing the audience.
HTML:
<div class="modal fade" id="createNewPostModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Create New Post</h4>
<button type="button" class="close" data-dismiss="modal">×</button>
</div>
<div class="modal-body">
<div class="container">
<form method="post" id="createNewPostForm">
<textarea rows="3" name="text" placeholder="Write something..."></textarea>
<div>
<p>Select audience to share</p>
<div>
<input type="checkbox" id="depACheckBox">
<label id="depACheckBoxLabel" for="depACheckBox"></label>
<input type="checkbox" id="depBCheckBox" >
<label id="depBCheckBoxLabel" for="depBCheckBox"></label>
<input type="checkbox" id="depCCheckBox">
<label id="depCCheckBoxLabel" for="CheckBox"></label>
</div>
</div>
<button type="submit" class="btn btn-success" onclick="return createNewPost(this.parentNode);" id="createNewPostButton" data-dismiss="modal">Share</button>
</form>
</div>
</div>
</div>
</div>
</div>
Different users have different departments to be shown and they are saved in mongoDB user document. I need to set the labels of the checkboxes on loading the modal.
I'm getting user's document on page load, so my attempt inside the getUser function:
$(document).ready(function() {
$("#createNewPostModal").on('load', function(){
document.getElementById('depACheckBoxLabel').innerText = window.user.depA.name;
document.getElementById('depBCheckBoxLabel').innerText = window.user.depB.name;
document.getElementById('depCCheckBoxLabel').innerText = window.user.depC.name;
});
});
I tried innerHTML as well but label still remains empty. How do I set the label text as or after the modal is shown?
If you call onload on anything other than window it will have no effect.
If you want to check for the #createNewPostModal div before running your function you can do something like the below example:
$(document).ready(checkModal);
function checkModal () {
if($('#createNewPostModal').is(':visible')){ //if the container is visible on the page
document.getElementById('depACheckBoxLabel').innerHTML = "this";
document.getElementById('depBCheckBoxLabel').innerHTML = "works";
document.getElementById('depCCheckBoxLabel').innerHTML = "now";
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="modal fade" id="createNewPostModal">
<p>Select audience to share</p>
<div>
<input type="checkbox" id="depACheckBox">
<label id="depACheckBoxLabel" for="depACheckBox"></label>
<input type="checkbox" id="depBCheckBox">
<label id="depBCheckBoxLabel" for="depBCheckBox"></label>
<input type="checkbox" id="depCCheckBox">
<label id="depCCheckBoxLabel" for="CheckBox"></label>
</div>
</div>
Feel free to adjust the check for :visible to something that suits your needs when referring to that container.
Additionally, as requested in your comment, if you want to call this function onclick you can do this:
$('button').click(checkModal);
function checkModal () {
if($('#createNewPostModal').is(':visible')){ //if the container is visible on the page
document.getElementById('depACheckBoxLabel').innerHTML = "this";
document.getElementById('depBCheckBoxLabel').innerHTML = "works";
document.getElementById('depCCheckBoxLabel').innerHTML = "now";
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="modal fade" id="createNewPostModal">
<p>Select audience to share</p>
<div>
<input type="checkbox" id="depACheckBox">
<label id="depACheckBoxLabel" for="depACheckBox"></label>
<input type="checkbox" id="depBCheckBox">
<label id="depBCheckBoxLabel" for="depBCheckBox"></label>
<input type="checkbox" id="depCCheckBox">
<label id="depCCheckBoxLabel" for="CheckBox"></label>
</div>
</div>
<button onclick="checkModal()">Click</button>
Just swap button for whatever element you want to trigger the function from.
Lastly, if it isn't necessary to wait for the #createNewPostModal div to load then just call your function like this and it should work:
$(document).ready(function() { document.getElementById('depACheckBoxLabel').innerHTML = window.user.depA.name; document.getElementById('depBCheckBoxLabel').innerHTML = window.user.depB.name; document.getElementById('depCCheckBoxLabel').innerHTML = window.user.depC.name; });
I'm having a problem in getting the value of input tag with a type of date which is place inside a modal. I'm trying to get this value using javascript. Here's my code:
HTML:
<form method="POST" action="{% url 'single_collection' %}">
{% csrf_token %}
<div class="modal-body form-horizontal">
<div class="form-group">
<label for="inputSQAID" class="col-sm-3 control-label">SQA Name</label>
<div class="col-sm-8">
<input type="hidden" name="sqa_name" id="sqa_name" value="{{ collectionlist.sqa_name }}">
</div>
</div>
<div class="form-group">
<label for="fromdate2" class="col-sm-3 control-label">From:</label>
<div class="col-sm-8">
<input type="date" class="form-control" name="fromdate2" id="fromdate2" max="{% now 'Y-m-d' %}" required>
<div class="modal-footer">
<button type="button" class="btn btn-primary pull-left" data-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-success" name="s_dl" id="s_dl" onclick="single_c()">Download</button>
</div>
</form>
Here's my javascript code, I'm just trying to display the value of the date from the input [type=date]:
<script type="text/javascript">
function single_c(){
var dates2 = document.getElementById('fromdate2').value;
document.write(dates2)
}
</script>
I tried to place the input tag outside the modal then it is working but when I put it back inside the modal it is not working. Any work around in here.
Your input does not have "value" property.
So you need to add "value" property to input,
And you need to call function single_c()
this function after how you type some text in input
Maybe something like this?
var date = "please enter a date";
dates.addEventListener('input',(e) => {
date = e.target.value
})
function single_c(){
document.write(date)
}
I had this problem too.
The main issue here is that if you have an id to target the value, the id must have the same name as the name attribute. I.e if you have an id="CheckingDate", your name="CheckingDate" else it won't work.
So this is the relevant part of my html-code. i tried binding the "formFriendsAll" scope to the ng-model.
<form ng-submit="submitForm()" >
<div class="col-sm-3">
<div class="form-group">
<label>Which Persons to show?</label>
<div class="radio">
<label>
<input type="radio" name="FriendsAll" ng-model="formFriendsAll" value="Friends" >
Friends
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="FriendsAll" ng-model="formFriendsAll" value="Alle">
All
</label>
</div>
<div>currently selected: {{formFriendsAll}}</div>
</div>
</div><td><input type="submit" class="btn btn-primary" value="Los!"/></td> </form>
This is the relevant js-code:
var challenge = angular.module('challengeApp', [])
challenge.controller('challengeController', function($scope) {
$scope.submitForm = function () {
alert($scope.formFriendsAll);
};
$scope.formFriendsAll = 'Friends';
});
I used the alert to test the change of value when i hit the submit button but i tried various methods like ng-changed, ng-click, ng-value. but nothing helped me solve the issue that my alert and "currently selected" stays on "Friends"
Any suggestions?
ok guys. seems like the AdminLTE.css i used in my head for the design of the radio buttons blocked the angular somehow
I have an application which has code like this:
<div class="step-tab" id="tab_2" ng-class="{'step--active': step == 2}" ng-controller="eventCatCtrl">
<div ng-if="step == 2" ng-include="'include/step2.php'"></div>
</div>
Inside my step2.php file I have:
<div class="form-group">
<label for="catTitle">Category Title <span>*</span></label><input type="text" class="form-control" id="catTitle" ng-model="catTitle" placeholder="Please enter your Category Title">
</div>
<div class="form-group">
<label for="catDes">Category Description</label><textarea name="" class="form-control" id="catDes" placeholder="Enter a description here" ng-model="catDes" id="" cols="10" rows="6"></textarea>
</div>
<div class="form-group">
<input ng-click="catValues(catTitle, catDes, $event)" type="button" class="btn btn-default" value="Add Category">
</div>
I have triggered the function catValues and did:
eventApp.controller("eventCatCtrl", function($scope){
$scope.catValues = function(catTitle, catDes, $event){
$scope.catTitle = null;
$scope.catDes = null;
}
});
However the null doesn't work, also a lot of other stuff that I have in that controller and in the functions work perfectly well but only this null doesn't work.
If I include ng-controller="eventCatCtrl" inside the step2.php file then the null works.
I would just like to know why the null is not clearing values of catTitle and catDes and why is everything else apart from that working fine.
that's because ng-include create a separate scope, so in your id="tab_2" has eventCatCtrl, so the scope of eventCatCtrl controller is the parent scope for the scope which create by ng-include, So if u try to assign null it will check for the scope of eventCatCtrl it cannot see the scope of ng-include, thats why its not going to assign null for ng-include models.
Do achieve this in your case u can define the models in ng-include template in eventCatCtrl like below,
eventApp.controller("eventCatCtrl", function($scope){
$scope.includeData = {};
$scope.catValues = function(catTitle, catDes, $event){
$scope.includeData.catTitle = null; // modify this
$scope.includeData.catDes = null;
}
});
and change your includes like this
<input type="text" class="form-control" id="catTitle" ng-model="includeData.catTitle" placeholder="Please enter your Category Title">
<textarea name="" class="form-control" id="catDes" placeholder="Enter a description here" ng-model="includeData.catDes" id="" cols="10" rows="6"></textarea>
HTML
<form class="controls" id="Filters">
<fieldset>
<div id="sample-showcase" class="noUi-target noUi-ltr noUi-horizontal noUi-background"></div>
<div id="rangespan-container">
<span id="min-value-span" class="range-spans"></span>
<input type="hidden" class="min-value-span">
<span class="range-spans">g</span>
<span id="max" class="range-spans"> - </span>
<span id="max-value-span" class="range-spans"></span>
<input type="hidden" class="min-value-span">
<span class="range-spans">g</span>
</div>
<div class="range-button checkbox">
<input type="checkbox" class="rangecheck"/></div>
</fieldset>
<fieldset>
<h3 class="sidetitle">Filter</h3>
<div class="breakfast-filter checkbox">
<input type="checkbox" class="checkbox1" value=".category-breakfast"/>
<label>Breakfast</label></div>
<div class="lunch-filter checkbox">
<input type="checkbox" class="checkbox2" value=".category-lunch"/>
<label>Lunch</label></div>
<div class="dinner-filter checkbox">
<input type="checkbox" class="checkbox3" value=".category-dinner"/>
<label>Dinner</label></div>
<div class="snacks-filter checkbox">
<input type="checkbox" class="checkbox4" value=".category-snacks"/>
<label>Snacks</label></div>
</fieldset>
<fieldset>
<h3 class="sidetitle">Sort</h3>
<div class="sort" data-sort="protein:asc">Low to High</div>
<div class="sort" data-sort="protein:desc">High to Low</div>
<div class="sort" data-sort="random">Random</div>
</fieldset>
<button id="Reset">Clear Filters</button>
</form>
Snippet of JS
bindHandlers: function(){
var self = this;
self.$filters.on('change', function(){
self.parseFilters();
});
self.$reset.on('click', function(){
self.$filters[0].reset();
self.parseFilters();
});
}
self.$reset = jQuery('#Reset'); it is defined higher in the code. Not sure if this is enough info.
Here is the link to the full code: Click Here
If you go to the home page click on some filters then try resetting. You should see it work like it's suppose to then take you to domain.com/?
Not sure why
Help please
button elements are submit buttons by default. You have to set type="button" if you to make them "dummy" buttons, i.e. they don't have a any default behavior:
type="button": The button has no default behavior. It can have client-side scripts associated with the element's events, which are triggered when the events occur.
<button type="button" id="Reset">Clear Filters</button>
Of course you could also set it to type="reset" and let the browser take care of resetting the form elements for you:
type="reset": The button resets all the controls to their initial values.
Then you could simplify your event handler to:
self.$reset.on('click', function(){
self.parseFilters();
});
It's not a huge change, but if the browser already offers this feature, why not make use of it?
Because you are using a button within the form and it is not prevented its default behavior.
Hence after resetting the form, the form is getting submitted.
You either have to return false after the function or preventDefault(). Try this.
self.$reset.on('click', function(e){
e.preventDefault();
self.$filters[0].reset();
self.parseFilters();
});
Or you need to set the type="button" for the button tag to make sure they are of type button and not submit.
<button id="Reset" type="button">Clear Filters</button>