How to remove models that are no longer bound to dom - javascript

I have a form that has a bunch of logic about which elements to show using ng-if. For example I might have a country drop down and if USA is selected it will show the state drop down which was conditioned upon an ng-if for country. Perhaps this was not the best way to do it so if there are recommendations for a different approach for the next project that will be appreciated but I need to finish this project with few major modifications.
The problem is if a user selects a country say USA and then a state, and then selects a different country. The state is still selected within the model. So how would I go about removing the state field. There are deeply nested ng-if's (think about 4-5 levels).
Example
<div ng-if="root.originCountry == 'PAK'">
<div ng-if="root.productType == 'Custom Football Jersey' || root.productType == 'Sublimated Football Jersey'">
<div class="control-group">
<label class="control-label" for="productTypeType">{{root.productType}} Type</label>
<div class="controls">
<select ng-model="root.productTypeType" ng-options="type for type in pakJerseyTypeList" bs-select required></select>
</div>
</div>
<div class="ordered-container">
<div ng-if="root.productTypeType">
<div class="control-group">
<label class="control-label" for="bodyColor">Body Color</label>
<div class="controls">
<select ng-model="root.bodyColor" ng-options="color for color in bodyColorList" bs-select required></select>
</div>
</div>
<div ng-if="root.bodyColor == 'Other'">
<div class="control-group no-count">
<label class="control-label" for="bodyColorPmsCode">Body Color PMS Code</label class="control-label no-count">
<div class="controls">
<input type="text" ng-model="root.bodyColorPmsCode" name='bodyColorPmsCode' required>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

You can utilize the ng-change directive to your advantage; set one on a parent select box and implement its handler to clear the values of any child select box depending on it.
Here's a quick snippet illustrating how to achieve this:
<select
ng-model="selectedCountry"
ng-options="country for country in countries"
ng-change="clearCity()">
</select>
<select
ng-model="selectedCity"
ng-if="isJapanSelected()"
ng-options="city for city in japanCities"
ng-change="setCity(selectedCity)">
</select>
var app = angular.module('myModule', []);
app.controller('MainCtrl', function($scope) {
$scope.countries = ['Japan', 'Brasil', 'England'];
$scope.selectedCountry = 'Brasil';
$scope.selectedCity = '';
$scope.japanCities = ['Tokyo', 'Yokohama', 'Osaka']
$scope.isJapanSelected = function() {
return $scope.selectedCountry == 'Japan';
};
$scope.getCity = function() {
return $scope.selectedCity;
};
$scope.setCity = function(city) {
$scope.selectedCity = city;
};
$scope.clearCity = function() {
if (!$scope.isJapanSelected()) {
$scope.selectedCity = '';
}
};
});
Live demonstration on plunker

Related

How do I create list the intended way I want

I have the following scripts:
Does calculation for me and lists them
function fromPortIdChange() {
fromportid = $('#fromPortId').val();
console.log(fromportid);
portIdRange(fromportid,toportid);
listOfNumbers=[];
}
function toPortIdChange() {
toportid = $('#toPortId').val();
console.log(toportid);
portIdRange(fromportid,toportid);
listOfNumbers=[];
}
function portIdRange(fromportid, toportid) {
fromportid = $('#fromPortId').val();
toportid = $('#toPortId').val();
fromportidlastvalueSliced = fromportid.slice(-5);
interfaceNameLength = fromportid.length-1;
interfaceName = fromportid.substring(0, interfaceNameLength);
console.log("length: " +interfaceNameLength);
console.log("interface name: " +interfaceName);
fromportidlastvalue = fromportidlastvalueSliced.split('/')[2]
console.log(fromportidlastvalue+ " FROM port id");
console.log("range is " +fromportid+ " to " +toportid);
toportidlastvalueSliced = toportid.slice(-5);
toportidlastvalue = toportidlastvalueSliced.split('/')[2]
console.log(toportidlastvalue+ " TO port id");
console.log(typeof(toportidlastvalue));
calculateRange(fromportidlastvalue, toportidlastvalue, interfaceName);
}
function calculateRange(fromportidlastvalue, toportidlastvalue, interfaceName) {
fromportidlastvalue = parseInt(fromportidlastvalue);
toportidlastvalue = parseInt(toportidlastvalue);
console.log(fromportidlastvalue + " type is " + typeof(fromportidlastvalue));
console.log(toportidlastvalue + " type is " + typeof(toportidlastvalue));
currentValue = fromportidlastvalue;
while(currentValue<=toportidlastvalue)
{
console.log(currentValue);
listOfNumbers.push(interfaceName+currentValue);
currentValue++;
}
$('#port_range').val(listOfNumbers);
}
Here is the html involved:
The part it is on the page and the one I am going to clone
<div id = first>
<div class="port">
<div class="row">
<div class="col-md-4">
<div class="form-group">
<label for="subnet_bit">From Port ID</label>
<select id="fromPortId" class="custom-select mb-3" onchange="fromPortIdChange();">
<option selected>Select</option>
{% for items in righttable %}
<option value={{items.0}}>{{items.0}}</option>
{%endfor%}
</select>
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label for="subnet_bit">To Port ID</label>
<select id="toPortId" class="custom-select mb-3" onchange="toPortIdChange();">
<option selected>Select</option>
{%for items in righttable%}
<option value={{items.0}}>{{items.0}}</option>
{%endfor%}
</select>
</div>
</div>
<div class="col-md-1">
<div class="form-group">
<div class="text-sm-center">
<br />
<button type="button" class="btn btn-outline-success btn-rounded"><i class="dripicons-plus" onclick="addButton();"></i></button>
</div>
</div>
</div>
</div>
</div>
</div>
The additional div i created for the clone to be in
<div id="morerows"></div>
This part is for the textarea
<p style="color:red;">If certain interface not needed, delete it</p>
<div class="row">
<div class="col-md-10">
<div class="form-group">
<label for="port_range">Port range</label>
<textarea class="form-control" id="port_range" rows="5"></textarea>
</div>
</div>
</div>
righttable comes from my django view
This script does the following: User choose FortyGigabitEthernet2/0/1 from the drop down of From Port ID and FortyGigabitEthernet2/0/5 from the drop down of To Port ID, it will list all the possible interface in portrange such as shown in the diagram, it lists FortyGigabitEthernet2/0/1, FortyGigabitEthernet2/0/2,FortyGigabitEthernet2/0/3,FortyGigabitEthernet2/0/4,FortyGigabitEthernet2/0/5
As you can see, there is a add button at the side. This is intended to to clone the drop down box for user to select other ports. Such as TenGigabitEthernet1/0/1 for a cloned From Port ID and TenGigabitEthernet1/0/3. So the following TenGigabitEthernet1/0/1, TenGigabitEthernet1/0/2, TenGigabitEthernet1/0/3 is add on to the existing FortyGigabitEthernet2/0/1, FortyGigabitEthernet2/0/2,FortyGigabitEthernet2/0/3,FortyGigabitEthernet2/0/4,FortyGigabitEthernet2/0/5 in the text area of Port Range
For the cloning of the drop down box:
function addButton(){
$('#first .port').clone().appendTo('#morerows')
}
Here comes the issues:
1. The add button works but i dont know is it lag or what. Sometime i have to click the add button multiple times before the cloned dropdown box appear.
2. The cloned drop down box are not working out like i want it to be. Like in the below picture. In 1st row we have FortyGigabitEthernet2/0/1 and Forty GigabitEthernet2/0/2. This is listed in the Port Range. But for the 2nd row of FortyGigabitEthernet2/0/4 and FortyGigabitEthernet2/0/5, it is not listed in the Port Range
Sorry for a very long post but is there anyway for me to achieve what I need. Appreciate if someone can help. Thanks in advance!

Cannot create property 'subjects' on number '1' using AngularJs

I want to select multiple subjects across one course but can't do so
I have two dropdown lists one for course selection and one for subjects selection. For multiple selection of the subjects I use the angular-chosen plugin, I can select multiple subjects only in the case when the Course is not selected from the dropdown list. But when I select the Course from the dropdown list then I can't select even one subject from the dropdown list
Following is my AddCourseController.js and related HTML
(function() {
var myApp = angular.module("myApp");
var AddCourseController = function($scope, CourseService, TeacherService) {
var onCourses = function(courses) {
$scope.courses = courses;
}
var onError = function(response) {
$scope.error = true;
$scope.errors = response.data;
};
CourseService.courses().then(onCourses, onError);
TeacherService.getSubjects().then(function(data) {
$scope.subjects = data
});
};
myApp.controller("AddCourseController", AddCourseController);
}());
<div class="form-group">
<label>Select Course</label>
<select ng-model="course" class="form-control"
ng-options="course.IdCourse as course.Name for course in courses track by course.IdCourse">
</select>
</div>
<div class="form-group" ng-class="{ 'has-error' :
addCourseForm.subjects.$invalid && !addCourseForm.subjects.$pristine }">
<label class="pull-left">Select Subjects</label>
<a class="pull-right btn btn-primary btn-xs" data-toggle="modal" data- target="#add-subject">Add Subject</a>
<select chosen multiple class="form-control"
ng-model="course.subjects"
ng-options="subject.IdSubject as subject.Name for subject in subjects">
</select>
<p ng-show="addCourseForm.subjects.$invalid &&
!addCourseForm.subjects.$pristine" class="help-block">Subject is required.
</p>
</div>
Change the course selector to return the entire course object to the ng-model:
<div class="form-group">
<label>Select Course</label>
<select ng-model="course" class="form-control"
ng-options="course ̶.̶I̶d̶C̶o̶u̶r̶s̶e̶ as course.Name for course in courses track by course.IdCourse">
</select>
</div>

Using jQuery validate on select list

I have the following javascript:
var $step = $(".wizard-step:visible:last"); // get current step
var validator = $("#WizardForm").validate(); // obtain validator
var anyError = false;
$step.find("input").each(function ()
{
if (!validator.element(this)) { // validate every input element inside this step
anyError = true;
}
});
This is successfully validating all my input fields but upon trying to apply a similar method to the select type using code:
$step.find("select").each(function () {
if (!validator.element(this)) { // validate every input element inside this step
anyError = true;
}
});
My HTML is as follows:
<div class="wizard-step" id="step1" visibility="hidden" style="display: block;">
<div class="row">
<div class="col-md-6 column ui-sortable">
<div class="form-group">
<label class="control-label col-md-4" for="Tariff_Type">Tariff Type</label>
<div class="col-md-8">
<select style="width:100%;height:35px;border-radius:4px;padding-left:10px;" id="TariffType" name="TariffType" class="form-control input required">
<option value="">Please Select Tariff Type</option>
<option value="keypad account">Say Hello To Budget Extra Discount</option>
<option value="bill pay account">Standard 24H</option>
</select>
<span class="field-validation-valid text-danger" data-valmsg-for="TariffType" data-valmsg-replace="true"></span>
</div>
</div>
</div>
</div>
</div>
How can I ensure that a TariffType value is selected using this method?
Try the .valid() method instead...
if (! $(this).valid()) { ...

Dropdowns not bound to ng-model in Angular

Something very basic I am missing but I am not able to figure out . I have three fields in a view , two of them are dropdowns.
<div class="form-group row">
<label for="GroupName" class="col-sm-4 form-control-label">Group Name : </label>
<div class="col-sm-8">
<input ng-model="referenceEdit.groupName" id="GroupName" class="form-control" type="text">
</div>
</div>
<div class="form-group row">
<label for="GroupType" class="col-sm-4 form-control-label">Group Type : </label>
<div class="col-sm-8">
<select name="selGroupType" id="selGroupType" class="form-control" ng-change="referenceEdit.populateGroupTypeDetails(selGroupType)" ng-options="groupType.value for groupType in referenceEdit.groupTypes track by groupType.id" ng-model="referenceEdit.groupType"></select>
</div>
</div>
<div class="form-group row">
<label for="GroupAssignmentMethod" class="col-sm-4 form-control-label">Group Assignment Method : </label>
<div class="col-sm-8">
<select name="selGroupAssignmentMethod" id="selGroupAssignmentMethod" class="form-control" ng-options="assignmentMethod.id for assignmentMethod in referenceEdit.assignmentMethods track by assignmentMethod.value" ng-model="referenceEdit.assignmentMethod"></select>
</div>
</div>
Now in controller , I am getting the results for these drop downs in this way :
var row_details = GroupMembershipReferenceServices.getReferenceDataRow();
referenceDataDropDownService.getDropDown(REFERENCE_DATA_CONSTANTS.GROUP_TYPE).success(function (result) {
$scope.referenceEdit.groupTypes = result;
$scope.referenceEdit.groupype = row_details.grp_typ;
}).error(function (result) {
alert("Unable to retrieve dropdown values");
});
referenceDataDropDownService.getDropDown(REFERENCE_DATA_CONSTANTS.GROUP_ASSIGNMENT_METHOD).success(function (result) {
$scope.referenceEdit.assignmentMethods = result;
$scope.referenceEdit.assignmentMethod = row_details.grp_assgnmnt_mthd;
}).error(function (result) {
alert("Unable to retrieve dropdown values");
});
Problem is values are getting populated , like
and we are displaying the values accordingly. The results are like
[0] {id:"1",value:"Chapter Non-Event"}
[1] {id:"2",value:"NHQ Campaign"}
But the row_details.grp_typ is "NHQ Campaign".
Even though I assign it , the drop down option is not selected accordingly .
Have I to assign it to the value property only ? What am I missing ?
use ng-repeat instead of ng-options
eg:
<select name="selGroupType" id="selGroupType" class="form-control" ng-change="referenceEdit.populateGroupTypeDetails(selGroupType)" ng-model="referenceEdit.groupType">
<option value="-1">---</option>
<option ng-repeat="groupType.value for groupType in referenceEdit.groupTypes track by groupType.id" value="{[{groupType.id}]}"> {[{groupType.value}]} </option></select>

Angular js not retrieving value by id's for dropdowns

I have an angular app with the following function:
$scope.search= function(){
var lname = document.getElementById("lastname").value;
var campus2 = document.getElementById("campusid").value;
StudentSearchService.getStudents(lname, campus2, function(data){
if(data!=null){
$scope.students = data;
}
});
}
and in the html page, I have the following 2 fields:
<div class="form-group col-lg-4 col-md-4">
<label for="lastname"> Last Name: </label>
<input type="text" id="lastname" placeholder="Last Name" class="form-control" />
</div>
<div class="form-group col-lg-4 col-md-4">
<label for="campus"> Campus:</label>
<select class="form-control" id="campusid" ng-model="newcampus" ng-options="camp.name for camp in campus" >
<option value="">ALL - District</option>
</select>
</div>
When i click to Search, the value for the lname is being retrieved just fine but the value from the dropdown campus2 is not being being initialized. Thus the call to the service is not being made properly.
Where am I going wrong?
First, it is not necessary to pick values from DOM elements if you are using Angular. It is way more easier to bind variables and use the variables themselves. I have created your example in JSFiddle: http://jsfiddle.net/rmadhuram/1n14eqfw/2/
HTML:
<div ng-app="app" ng-controller="FormController">
<div class="form-group col-lg-4 col-md-4">
<label for="lastname">Last Name:</label>
<input type="text" id="lastname" ng-model="lastName" placeholder="Last Name" class="form-control" />
</div>
<div class="form-group col-lg-4 col-md-4">
<label for="campus">Campus:</label>
<select class="form-control" id="campusid" ng-model="newcampus" ng-options="camp.name for camp in campus">
</select>
</div>
<button ng-click='search()'>Search</button>
</div>
JavaScript:
angular.module('app', [])
.controller('FormController', ['$scope', function ($scope) {
$scope.campus = [
{ name: 'campus 1' },
{ name: 'campus 2' }
];
$scope.newcampus = $scope.campus[0];
$scope.lastName = '';
$scope.search = function() {
alert('Name: ' + $scope.lastName + ' Campus: ' + $scope.newcampus.name);
};
}]);
Hope this helps!
The biggest place you are going wrong is by trying to access values directly from the DOM inside your Angular controller, rather than relying on Angular to bind properties on the scope to your inputs and handle all of that for you.
I have made a version in Plunkr that demonstrates the "Angular way" of approaching this.
The guts of the controller is:
app.controller('MainCtrl', function($scope, StudentSearchService) {
$scope.campus = [
{name: "Campus 1"},
{name: "Campus 2"}
];
$scope.searchParams = {
lastName: "",
campus: null
};
$scope.search = function() {
StudentSearchService.getStudents($scope.searchParams.lastName,
$scope.searchParams.campus.name,
function(data) {
if (data !== null) {
$scope.students = data;
}
});
}
});
And then your markup becomes:
<div class="form-group col-lg-4 col-md-4">
<label for="lastname">Last Name:</label>
<input type="text" id="lastname" placeholder="Last Name" class="form-control" ng-model="searchParams.lastName" />
</div>
<div class="form-group col-lg-4 col-md-4">
<label for="campus">Campus:</label>
<select class="form-control" id="campusid" ng-model="searchParams.campus" ng-options="camp.name for camp in campus">
<option value="">ALL - District</option>
</select>
</div>
Note the use of ng-model to bind the inputs to scope properties. Also note there is no DOM access code in the controller. This makes it easier to test, and allows you to test your controller without any DOM at all. That is the core philosophy Angular is based around.

Categories

Resources