Rebind of data-ng-click not working - angularjs

I am using this template and binding data with it
<div id="groupSegment" data-ng-repeat="q in CurrentQuestion">
Segment Info
<div>{{q.SegmentName}}</div>
Questions:
<div>{{q.Title}}</div><div>{{q.Description}}</div>
<input type="button" value="Previous" id="d{{q.PrevQuestIndex}}" data-ng-click="ChangeQuestion({{q.PrevQuestIndex}})" /><br /> <input id="d{{q.NextQuestIndex}}" type="button" value="Next" data-ng-click="ChangeQuestion({{q.NextQuestIndex}})" />
</div>
Issue coming that on click of Next and Previous its not updating the value of index when clicking next time.
Html shows that the updated value is there but when i am clicking then its showing the value that was set when html renderd
Here is the funtion that firing on click.
$scope.ChangeQuestion = function (index) {//this indux value not getting changed
if (index < 0 || index > $scope.Questions.length)
return;
$scope.CurrentQuestion = [];
var i = 0;
$($scope.Questions[index]).each(function () {
if (i == 0) {
$scope.CurrentQuestion.push({ Title: this.Title, Description: this.Description,SegmentName: this.SegmentName, NextQuestIndex: index + 1, PrevQuestIndex: index - 1 });
}
i++
});
$scope.$apply();
};
So how I can refresh this on click parameter

Normally I'm using ng-click instead of data-ng-click which you used..
Also You don't need to pass parameters with {{}} if you use it inside ng- tag.
Change it as ng-click="ChangeQuestion(q.PrevQuestIndex)"
<div id="groupSegment" data-ng-repeat="q in CurrentQuestion">
Segment Info
<div>{{q.SegmentName}}</div>
Questions:
<div>{{q.Title}}</div><div>{{q.Description}}</div>
<input type="button" value="Previous" id="d{{q.PrevQuestIndex}}" ng-click="ChangeQuestion(q.PrevQuestIndex)" /><br />
<input id="d{{q.NextQuestIndex}}" type="button" value="Next" ng-click="ChangeQuestion(q.NextQuestIndex)" />
</div>

Related

AngularJS: ng-change does not work when value changes on ng-click

I have created some control buttons to handle server side pagination. It has 4 buttons (First Page, Previous Page, Next Page and Last Page), a page counter which is an input text field and a drop-down to select a number of rows you want to see.
The page counter is defined as vm.currentPage in the controller, which can be manipulated by the buttons or typing a new value in the input, and the drop-down as vm.rowsPerPage. For both these elements I have declared a ng-change with a function inside that eventually has to get the data, called vm.setPagingData();
My problem here is that this function is not getting fired when I use one of the control buttons, even though vm.currentPage inside the input text is changing.
There is no problem when I directly change the value in the input or when I use the dropdown to select a number of rows I want to see.
Below I have a sample code with the function setPagingData() incrementing a value by 1 every time it been called. Plnkr link: http://plnkr.co/edit/qHrTC9gkntSw9IfgeJ5T?p=preview
html:
<!--Back Buttons-->
<button ng-disabled="ctrl.currentPage <= 1" ng-click="ctrl.currentPage = 1;"> << </button>
<button ng-disabled="ctrl.currentPage <= 1" ng-click="ctrl.currentPage = ctrl.currentPage - 1"> < </button>
<!--Current page count-->
<span><input type="text" ng-model="ctrl.currentPage" ng-change="ctrl.setPagingData()" /> of {{ctrl.totalPages}}</span>
<!--Next buttons-->
<button ng-disabled="ctrl.currentPage >= ctrl.totalPages" ng-click="ctrl.currentPage = ctrl.currentPage + 1;"> > </button>
<button ng-disabled="ctrl.currentPage >= ctrl.totalPages" ng-click="ctrl.currentPage = ctrl.totalPages;"> >> </button>
<br><br>
Show:
<select ng-model="ctrl.rowsPerPage" ng-change="ctrl.setPagingData()">
<option value="10" ng-selected="ctrl.rowsPerPage === '10'">10 rows</option>
<option value="20" ng-selected="ctrl.rowsPerPage === '20'">20 rows</option>
<option value="40" ng-selected="ctrl.rowsPerPage === '40'">40 rows</option>
<option value="60" ng-selected="ctrl.rowsPerPage === '60'">60 rows</option>
</select>
<br><br>
{{ctrl.test}}
controller:
vm.currentPage = 1;
vm.totalPages = 16;
vm.rowsPerPage = "20";
vm.test = 0;
vm.setPagingData = function(){
vm.test++;
}
Should I define the logic of the buttons inside controller instead of inside the ng-change or something? Or is there a way to keep it in the HTML?
As described in the documentation, ng-change is triggered when the user changes the value of the input field manually.
Available solutions:
Using ngClick
Call ctrl.setPagingData() inside the ng-click of your buttons
<button ng-click="ctrl.currentPage = ctrl.currentPage + 1; ctrl.setPagingData();" ng-disabled="ctrl.currentPage >= ctrl.totalPages"> > </button>
<button ng-click="ctrl.currentPage = ctrl.totalPages; ctrl.setPagingData();" ng-disabled="ctrl.currentPage >= ctrl.totalPages"> >> </button>
Using $scope.$watch
Watch for changes to the variable vm.rowsPerPage:
$scope.$watch(function() {
return vm.rowsPerPage;
}, function() {
vm.setPagingData();
});

How to update scope on form Submit, when ng-model value changes?

I am creating an edit customer form and passing an object of 30 key value pairs. I am then using ng-repeat to populate input fields of a form. All form is displayed nicely and with passed key, values. I can also change the value of any input field.But when I submit the form, it takes the old scope object which I passed initially in the form, leaving behind my changes. I need to submit my changed object Now. How To do that? I searched much but can't find the solution to this.
var app = angular.module("customerModule", []);
app.controller('crudController', function($scope, $http) {
$scope.Customers = //object from Ap with almost 30 key,values
$scope.edit = function() {
console.log($scope.Customers);
//the above line prints the API called object where as I am editing the values of ng-model in my form. and I need the form submitted values
}
});
<div ng-app="customerModule" ng-controller="crudController">
<form name="as" ng-submit="edit()">
<ul>
<li ng-repeat="(key, val) in Customers " ng-hide="(key=='total' || key=='paid' || key=='customfields' || key=='owing')" ng-if="key!='customfields'">
<label class="label"> {{key}}</label> <input type="text" ng-model="val" />
</li>
<li ng-repeat="(key, val) in Customers.customfields">
<label class="label"> {{key}}</label> <input type="text" ng-model="val" />
</li>
<button type="submit"><i class="fa fa-plus-circle" aria-hidden="true"></i><span> Edit Customer</span></button>
<ul>
</form>
</div>
Use ng-model="Customer[key]".
You're using the local variable val referencing the value. That's basically aquivalent to doing
var val = Custom['foo'];
val = 'newValue';
That won't change the value of Custom['foo'], right?
But the following will:
Custom['foo'] = 'newValue';

Call the first <span> in a scrollbar when press enter using angularjs

I have a text box which is using for search.When enter the characters it searches the values and shows one by one in a scrollbar. When i click on any found value it redirects to the related page but when press enter it should call first value in that scrollbar.Below is my code.
<div><input type="text" value="" placeholder="search" ng-model="searchText" name="testName" ng-keyup="search()"></div>
<div class="scroll" ng-show="searchText.length" ng-hide="!searchText.length">
<div ng-repeat="relatedData in data">
<span ng-click="showDetails(relatedData)" ng-model="searchText">{{ relatedData }} </span><br />
</div>
</div>
and below is my script code:
$scope.showDetails = function(relatedData) {
$http.get("searchInfo.json").success(function(response) {
var searchT = relatedData;
$http.get(searchT+'Details.json').success(function(response) {
$scope.details = response;
$scope.searchText = "";
});
});
}
Could you please help to call first value in multiple values scrollbar,Thanks.
One way would be to wrap your search field in a form element:
<form ng-submit="showDetails(data[0])">
<input type="text"
value=""
placeholder="search"
ng-model="searchText"
name="testName"
ng-keyup="search()">
</form>
ng-submit will catch the form submit event triggered by pressing Enter.

parsleyjs with multi steps form

I'mn creating a multi step form wizard (using Twitter Bootstrap Wizard) and looking at the Parsley multi step example I'm not sure how I would implement it if I have more then two steps my current form has at least 4 steps.
This is what I don't understand
<span class="next btn btn-info pull-right" data-current-block="1" data-next-block="2">Next ></span>
My next button is constant
Here is the parsley example
<form id="demo-form" data-parsley-validate>
<div class="first block1 show">
<label for="firstname">Firstname:</label>
<input type="text" name="firstname" data-parsley-group="block1" required/>
<label for="lastname">Lastname:</label>
<input type="text" name="lastname" data-parsley-group="block1" required />
<span class="next btn btn-info pull-right" data-current-block="1" data-next-block="2">Next ></span>
</div>
<div class="second block2 hidden">
<label for="fullname">Email:</label>
<input type="text" name="fullname" required data-parsley-type="email" data-parsley-group="block2" />
<span class="next btn btn-info pull-left" data-current-block="2" data-next-block="1">< Previous</span>
<input type="submit" class="btn btn-default pull-right" />
</div>
</form>
<script type="text/javascript">
$(document).ready(function () {
$('.next').on('click', function () {
var current = $(this).data('currentBlock'),
next = $(this).data('nextBlock');
// only validate going forward. If current group is invalid, do not go further
// .parsley().validate() returns validation result AND show errors
if (next > current)
if (false === $('#demo-form').parsley().validate('block' + current))
return;
// validation was ok. We can go on next step.
$('.block' + current)
.removeClass('show')
.addClass('hidden');
$('.block' + next)
.removeClass('hidden')
.addClass('show');
});
});
</script>
The solution or workaround is pretty simple. It's best just to use Bootstrap Wizard methods your going to want to have the following
$('#w4').bootstrapWizard({
tabClass: 'wizard-steps',
nextSelector: 'ul.pager li.next',
previousSelector: 'ul.pager li.previous',
firstSelector: null,
lastSelector: null,
onNext: function( tab, navigation, index, newindex ) {
var current = index,
next = current + 1;
// only validate going forward. If current group is invalid, do not go further
// .parsley().validate() returns validation result AND show errors
if (next > current)
if (false === $('#bioForm').parsley().validate('step' + current))
return false;
// validation was ok. We can go on next step.
$('.step' + current)
.removeClass('show')
.addClass('hidden');
$('.step' + next)
.removeClass('hidden')
.addClass('show');
}
});
I know this is late, but could help someone else in need .Had similar problem and this is how i solved it.
i added this to each control i need to validate on each steps
add this to step1 controls : data-parsley-group="block-1"
add this to step2 controls: data-parsley-group="block-2"
....keep increasing for each steps.
in your bootstrapwizard javascript add the code below in the 'OnNext' fuction.
$('#form').bootstrapWizard({
tabClass: 'wizard-steps',
'onNext': function (tab, navigation, index) {
var $valid = $("#form").parsley().validate({ group: 'block-' + index });
if(!$valid) {
return false;
}
}
});
Hope this helps you out.

AngularJS Dynamically Adding Control In Repeater to Form Causes Submit

I have a form which represents an object and an array of sub-objects contained in a repeater. I want to dynamically add sub-objects to the array. When I add a sub-object the form gets submitted unexpectedly.
See this example:
http://plnkr.co/edit/TUblgmb7N710nPL7s5tU?p=preview
My form looks like this:
<form ng-submit="handleSubmit()" ng-controller="TestController">
<div>Some Input: <input type="text"></div>
<div ng-repeat="obj in model.children">
<input type="text" ng-model="obj.text" />
</div>
<button ng-click="addChild()"> Add Child</button>
</form>
The controller looks like this...
Controllers.controller('TestController', ["$scope", function($scope) {
$scope.model = {
name: "Some Text",
children: []
};
$scope.handleSubmit = function() {
alert("Form Submitted!");
}
$scope.addChild = function() {
$scope.model.children.push({text:"Foo"});
}
}]);
Click the "Add Child" buttton. The UI is updated as expected but the form gets submitted.
I can work around this by putting the submit function in ng-click on the Save button instead of ng-submit on the form but this seems like unexpected behaviour. Can anyone explain?
The default attribute type The HTML button tag <button>My Button</button> triggers the submit event as <input type = "submit"...> does.
Now, following the idea of #GruffBunny, I have added a pInputType parameter to your method to show what button was clicked:
$scope.addChild = function(pInputType) {
$scope.model.children.push({text:"Foo", inputType : pInputType });
}
Then in the HTML block, the attribute inputTypewas added within the loop as follow:
<div ng-repeat="obj in model.children">
<hr />
<h3>{{obj.inputType}}</h3>
<div>New Input: <input type="text" ng-model="obj.text" /></div>
</div>
Finally, here are the buttons for testing the code:
<!-- With Input Type -->
<h2>Input type Button</h2>
<input type="button" ng-click="addChild('Input type Button')" value="Btn Add Child" />
<hr />
<!-- With Normal Anchor -->
<h2>HTML Anchor</h2>
Add Child Link
<hr />
<!-- Adding Bootstrap -->
<h2>HTML Bootstrap Anchor</h2>
Add Child Link
<hr />
<!-- Button Tag -->
<h2>HTML Button Tag (Triggers SUbmit Events)</h2>
<button ng-click="addChild('Triggers Submit Events')">Add Child</button>
<hr />
Here is the complete plunker: http://plnkr.co/edit/N4hSjG
For further information about this behavior, you can read this Stack Overflow question: <button> vs. <input type="button" />. Which to use?
I hope it could be useful this explanation for anyone.

Resources