Remove select options based on button click in angular js - angularjs

In my app i have a select html which has following options
"Addition","Deletion","Duplicate","Member Duplicate"
Above drop down page is common for both add and edit screen. As of now if we come from any addition click or edit click drop-down has all options. (Note: drop-down binds at the time of loading page itself. we will show/hide depending on click)
As per new requirement I need to remove all other options except "Addition" in addition click and remove "Addition" option in edit click.
select html:
<select name="ReasonID" required ng-model="member.ReasonID" class="form-control" ng-options="reason.ID as reason.Description for reason in reasons |orderBy: reason.Description"></select>
Js
$scope.manageMember = function (member) {
$scope.showGrid = false;
$scope.showForm = true;
reset();
$scope.memberTemp = member;
angular.extend($scope.member, member); };
Please let me know if you need more details from my end.

Update :
Here the full sample code and working demo with dummy data.
HTML
<div ng-app>
<h2>Todo</h2>
<div ng-controller="TodoCtrl">
<select name="ReasonID" required ng-model="member.ReasonID" class="form-control" ng-options="reason.ID as reason.Description for reason in reasons |orderBy: reason.Description"></select>
<br/>
<input type="button" ng-click="manageMember(undefined)" value="add"/>
<input type="button" ng-click="manageMember('bla bla bla')" value="edit"/>
</div>
</div>
JS
function TodoCtrl($scope) {
$scope.reasons = [{ID:1,Description :"Addition"}, {ID:2,Description :"Deletion"},{ID:3,Description :"Duplicate"},{ID:4,Description :"Member Duplicate"}];
var reasonsTemp =angular.copy($scope.reasons);
$scope.manageMember = function (member) {
console.log(reasonsTemp)
$scope.reasons=reasonsTemp;// assign global object to model
$scope.showGrid = false;
$scope.showForm = true;
$scope.memberTemp = member;
var EditArray=[];
for(var i = 0 ; $scope.reasons.length>i;i++)
{
if($scope.reasons[i].Description === ($scope.memberTemp == undefined ? "Addition" : "bla bla bla"))// condition for is this addition or not
{
EditArray = $scope.reasons[i];
break;
}
else // if is it not addition, then addition only offect that object. because we were already assigned original value globally
{
if($scope.reasons[i].Description!=="Addition")
{
EditArray.push($scope.reasons[i])
}
}
}
$scope.reasons=EditArray;
console.log($scope.reasons);
}
}
Working Demo On console window

Try this,
HTML
<select ng-model="selectedOption">
<option ng-show="reason.show" ng-repeat="reason.ID as reason.Description for reason in reasons |orderBy: reason.Description">{{reason.ID}}</option>
</select>
JS
$scope.manageMember = function (member) {
$scope.showGrid = false;
$scope.showForm = true;
reset();
$scope.memberTemp = member;
angular.extend($scope.member, member);
if(member){
for(var i = 0 ; $scope.reasons.length>i;i++)
{
$scope.reasons[i].show = true;
if($scope.reasons[i].ID == "Addition"){$scope.reasons[i].show = false;}
}
}else{
for(var i = 0 ; $scope.reasons.length>i;i++)
{
$scope.reasons[i].show = false;
if($scope.reasons[i].ID == "Addition"){$scope.reasons[i].show = true;}
}
}
}

Suppose you have two buttons as,
<input type="button" ng-click="toAdd=true">Add</input>
<input type="button" ng-click="toAdd=false">Edit</input>
And the select box code should be like,
<select ng-model="selectedOption">
<option ng-show="toAdd">Addition</option>
<option ng-show="!toAdd">Deletion</option>
<option ng-show="!toAdd">Duplicate</option>
<option ng-show="!toAdd">Member Duplicate</option>
</select>
Hope this helps.

Related

Changing multi select element with Angularjs

There is a multi select element in my page.
<div class="form-group">
<select ng-show="'#Model.IsWinnerFilterVisible'" class="selectpicker" multiple title="Kazanan" ng-model="MainWinnerFilterSelected" id="ddl_winnerid"
data-ng-options="MainWinnerFilter.Id as MainWinnerFilter.Name for MainWinnerFilter in MainWinnerFilters"></select>
</div>
<div class="form-group">
<select ng-show="'#Model.IsReasonFilterVisible'" class="form-control" title="İlgilenilmeme Nedeni" ng-model="MainReasonFilterSelected" id="ddl_reasonid" ng-init="MainReasonFilterSelected= #Model.SelectedReason"
data-ng-options="MainReasonFilter.Id as MainReasonFilter.Name for MainReasonFilter in MainReasonFilters">
<option value="">İlgilenilmeme Nedeni</option>
</select>
</div>
And i can load this first with the code below
$scope.MainWinnerFilterSelected = #Html.Raw(Json.Encode(Model.SelectedWinner));
I want to reload this element with a new data but it dosent work.
$scope.loadReasonAndWinner= function() {
var productGroupFilters=$scope.productGroupFilterSelected;
var res = $http.post('#Url.Action("GetWinnerAndReasonList", "Details")', {'selectedProductGroup':productGroupFilters});
res.success(function(data, status) {
$scope.MainWinnerFilters=data.WinnerList;
$scope.MainReasonFilters=data.NotInterestingReasonList;
});
res.error(function(data, status) {
$scope.addError("alert-danger","Bir Hata oluştu.","Error");
});
}
In controller;
[HttpPost]
public ActionResult GetWinnerAndReasonList(int SelectedProductGroup)
{
var detail = new DetailsModel();
detail.SelectedProductGroup = SelectedProductGroup;
var winnerList = BiddingService.RetrieveWinners(null, VariableHelper.ListOf(detail.SelectedProductGroup));
detail.WinnerList = BiddingService.TranslateToFilter(winnerList);
var notInterestedActionStatus = new List<int>() { VariableHelper.Int(ActionStates.NotInterested) };
var notInterestingReasonList = BiddingService.RetrieveActionReason(notInterestedActionStatus, VariableHelper.ListOf(detail.SelectedProductGroup));
detail.NotInterestingReasonList = BiddingService.TranslateToFilter(notInterestingReasonList);
return Json(detail);
}
New data comes true and it works with combobox (MainReasonFilter) but it dosent change the items in multiselect element(MainWinnerFilter). Any idea with that?

AngularJS ng-select issue

I've got a simple page selector I'm using in an Angular 1.5 page. The select works for the most part, but the ng-selected part does not.
If I'm on page 3, (which is ironically the last page, not sure if that matters) 3 is selected by default. If I'm on page 1 or 2, the first item (blank) is selected. I'm not super versed in Javascript, but figured it might be a type issue. Tried settings $scope.thisPage with parseInt(page) and page.toString() just in case it did something under the sheets I wasn't aware of, but it all turned out the same.
app.controller('myCtrl', ['$scope','$route','$routeParams', function($scope,$route,$routeParams) {
$scope.pages = [];
var page = $routeParams.p ? $routeParams.p : 1
$scope.thisPage = page;
for (var i = 0; i < 5; i++) {
$scope.pages.push(i);
}
}]);
<form name="myForm">
<select ng-model="selectedPage" ng-change="switchPage(selectedPage)">
<option ng-repeat="p in pages" ng-value="{{p}}" ng-selected="{{p == thisPage}}">{{p}}</option>
</select>
</form>
You need no set selected property
<form name="myForm">
<select ng-model="selectedPage" ng-change="switchPage(selectedPage)">
<option ng-repeat="p in pages" ng-value="{{p}}">{{p}}</option>
</select>
</form>
Instead bind the selectedPage value with thisPage
app.controller('myCtrl', ['$scope','$route','$routeParams', function($scope,$route,$routeParams) {
$scope.pages = [];
var page = $routeParams.p ? $routeParams.p : 1
$scope.selectedPage= page; ////////////////////////////////
for (var i = 0; i < 5; i++) {
$scope.pages.push(i);
}
}]);
ngSelected require an expression as following p == thisPage and not {{p == thisPage}}
Source : https://docs.angularjs.org/api/ng/directive/ngSelected

AngularJS clear validation $error after input's changing

Updated question with fiddle.
Original is here: https://stackoverflow.com/questions/31874313/angularjs-clean-remote-validation-error-after-change-input
In my form I have two validations. First is local, second is remote.
So this is my example
<form ng-controller="MyCtrl" name="Form">
<div class="form-group">
<label class="control-label">
First Name
</label>
<input type="text" class="form-control" name="firstName" ng-model="myModel.firstName" required />
<span class="error" ng-if="Form.firstName.$dirty && Form.firstName.$invalid" ng-repeat="(e, b) in Form.firstName.$error">{{e}}</span>
</div>
<input type="submit" ng-click="submit(Form)">
</form>
Here is Controller
function MyCtrl($scope, $element) {
$scope.submit = function (form) {
if (form.$invalid) {
renderErrors(form);
return;
}
console.log('local validation passed');
// imitation of remote error
// send, then data
if($scope.myModel.firstName === 'Tom')
renderServerErrors({firstName: ['Already in use']}, form);
else
alert('Success');
}
/**
* Errors will appear below each wrong input
*/
var renderErrors = function(form){
var field = null;
for (field in form) {
if (field[0] != '$') {
if (form[field].$pristine) {
form[field].$dirty = true;
}
}
}
};
/**
* Server errors will appear below each wrong input
*/
var renderServerErrors = function(err, form){
var field = null;
_.each(err, function(errors, key) {
_.each(errors, function(e) {
form[key].$dirty = true;
form[key].$setValidity(e, false);
});
});
}
}
http://jsfiddle.net/uwozaof9/6/
If you type 'Tom' into input - you will never submit form more..
And I want to delete server errors from input's error stack on it's change.
Please help!
It seems you only set invalid but don't set valid after it was corrected. IF you are doing yourself you also have to implement setting $valid if the imput is valid.

Angularjs bindings not being updated

I am facing a problem with my angular js bindings not being updated correctly.
I am trying to achieve a way to hide certain form elements and show others by clicking a "next" button.
I have setup some objects in my controller to hold values for input text fields and menu dropdowns, I also have setup a couple of button (next and previous and add) button to be able to add new objects and a next and previous buttons to be able to navigate between the different stored objects.
The problem that I am facing is that the input text field is being updated correctly when i press the next and previous button however the dropdown menus are not.
This is a link to a jsfiddle to help show the problem:
http://jsfiddle.net/bLs9yu3f/
Found two issues with the code in your Fiddle:
First, when assigning programOutcomes to the affects key of your objects (both when creating the initial one and pushing to add a new one) you where assigning programOutcomes directly, which assigns a pointer to the original array and doesn't create a copy. There are many ways to do this. I chose affects: JSON.parse(JSON.stringify(programOutcomes)). See the example below.
$scope.output.outcomes.push({
outcome: '',
affects: JSON.parse(JSON.stringify(programOutcomes))
});
Second, in the for loop of your addCourseOutcome function you refer to $scope.output.outcomes[0] instead of the latest $scope.output.outcomes you just pushed. The following code fixes this issue.
var lastest = $scope.output.outcomes.length - 1;
for (var i = 0; i < programOutcomes.length; i++) {
$scope.output.outcomes[lastest].affects[i].how = '';
}
This is a fork of your Fiddle with the corrections I mentioned above: http://jsfiddle.net/JohnnyEstilles/uz8zf2b0/.
angular.module('myapp', []).controller('ProgramsController', ['$scope',
function($scope) {
var programOutcomes = [{
outcome: 'po1'
}, {
outcome: 'po2'
}, {
outcome: 'po3'
}, {
outcome: 'po4'
}];
$scope.input = {
outcomeCounter: 0,
programOutcomes: programOutcomes,
actions: ['', 'I', 'E', 'R']
};
$scope.output = {
outcomes: [{
outcome: '',
affects: JSON.parse(JSON.stringify(programOutcomes))
}]
};
for (var i = 0; i < programOutcomes.length; i++) {
$scope.output.outcomes[0].affects[i].how = '';
}
$scope.nextOutcome = function() {
$scope.input.outcomeCounter++;
};
$scope.previousOutcome = function() {
$scope.input.outcomeCounter--;
};
$scope.deleteCourseOutcome = function() {
$scope.output.outcomes.splice($scope.input.outcomeCounter, 1);
$scope.input.outcomeCounter--;
};
$scope.addCourseOutcome = function() {
$scope.output.outcomes.push({
outcome: '',
affects: JSON.parse(JSON.stringify(programOutcomes))
});
/**
* create a 'how' property in the affects array
* to be used for storage of I, E, R
*/
var lastest = $scope.output.outcomes.length - 1;
console.log($scope.output.outcomes[lastest].affects);
for (var i = 0; i < programOutcomes.length; i++) {
$scope.output.outcomes[lastest].affects[i].how = '';
}
/**
* increment the outcomeCounter
*/
$scope.input.outcomeCounter++;
};
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="myapp">
<div ng-controller="ProgramsController">
<div class="form-group">
<label for="outcome">Outcome</label>
<input id="outcome" placeholder="Outcome" class="form-control" ng-model="output.outcomes[input.outcomeCounter].outcome">
</div>
<div class="form-group">
<table class="table table-striped">
<tr ng-repeat="programOutcome in input.programOutcomes">
<td>{{programOutcome.outcome}}</td>
<td>
<select ng-model="output.outcomes[input.outcomeCounter].affects[$index].how" ng-options="value for value in input.actions">
</select>
</td>
</tr>
</table>
</div>
<div class="form-group">
<button class="btn" ng-click="addCourseOutcome()">Add outcome</button>
<button class="btn" ng-click="nextOutcome()"
ng-if="output.outcomes.length>1 && input.outcomeCounter !== (output.outcomes.length - 1)">
Next
</button>
<button class="btn" ng-click="previousOutcome()"
ng-if="output.outcomes.length>1 && input.outcomeCounter > 0">
Previous
</button>
<button class="btn btn-warning" ng-click="deleteCourseOutcome()">Delete outcome</button>
</div>
</div>
</body>

Need to require only one of a group of fields with Parsley

I am using Parsley.js for validating a form submission on a project. One of my needs is to have Parsley require that at least one of three fields have data in them, and only fail validation if none of the three fields has data.
I am not sure from the documentation, how to accomplish this. I already have Parsley validation working on the rest of the form.
You can do that with a custom validator like so
var CheckReccursion = 0;
window.Parsley.addValidator('min3', {
validateString: function (value, requirement, instance) {
var notice =$('#notice').html(' ');
var group = $(requirement);//a class
var FieldsEmpty = 0;
var FieldsNotEmpty = 0;
var count = 0
group.each(function () {
var _val = $(this).val()
var length = _val.length
if (length > 0) {
FieldsNotEmpty++;
}
else {
FieldsEmpty++;
}
count++;
})
var isValid = (FieldsNotEmpty >=1)
//recursively execute
group.each(function (index) {
if (CheckReccursion === index) {
CheckReccursion++;
$(this).parsley().validate();
CheckReccursion = 0;
}
})
return isValid;
}
});
$(function () {
var ok=false;
var notice =$('#notice');
$('#form1').parsley().on('form:validated', function(formInstance) {
ok = formInstance.isValid({force: true});
})
.on('form:submit', function() {
if(!ok){
notice.html('Please fill at least 1 field');
return false;
}
else{
notice.html('okay');
return false;//change to true to submit form here
}
});
});
then add parsley attributes to the group of fields like so:
<form id="form1" data-parsley-validate="true">
<input type="text" name="field1"
data-parsley-min3 = ".group1"
data-parsley-min3-message = "At least 1 must be filled"
class="group1">
<input type="text" name="field2"
data-parsley-min3 = ".group1"
data-parsley-min3-message = "At least 1 must be filled"
class="group1">
<input type="text" name="field3"
data-parsley-min3 = ".group1"
data-parsley-min3-message = "At least 1 must be filled"
class="group1">
<span id="notice"></span>
<input type="submit" value="Submit">
</form>
Check out this fiddle https://jsfiddle.net/xcoL5Lur/6/
My advice is to add hidden checkbox element with the attribute:
data-parsley-mincheck="1"
now just add javascript code that checks the hidden checkbox attribute when your form input has value (and the opposite).
notice that you will need to add extra attribute to your hidden checkbox:
data-parsley-error-message="Please fill at least one input"
Another approach is to using data-parsley-group and the isValid({group,force}) method.
<input type="text" name="input1" data-parsley-group="group1">
<input type="text" name="input2" data-parsley-group="group2">
<input type="text" name="input3" data-parsley-group="group3">
$('#myform').parsley().on('form:validate', function (formInstance) {
if(formInstance.isValid({group: 'group1', force: true}) ||
formInstance.isValid({group: 'group2', force: true}) ||
formInstance.isValid({group: 'group3', force: true})) {
//do nothing
}
else {
$('#errorContainer').html('You must correctly fill at least one of these three groups!');
formInstance.validationResult = false;
}
});
you can add as many as parsley's attributes as you wish, like data-parsley-type="email" that will be validated when the given input is not empty.
we set the force: true because it it forces validation even on non-required.fields.
the html render for the errorContainer is needed because the isValid method does not affect UI nor fires events.

Resources