Changing the target of input slider value in jQuery - jquery-slider

I'm using JQuery Simple Slider to transform a textbox to a slider.
It includes the following script which
Adds a <span class="output"></span> after its position in the DOM and
Binds the value to the span when it changes.
Here it is:
<script>
$("[data-slider]")
.each(function () {
var input = $(this);
$("<span>")
.addClass("output")
.insertAfter($(this));
})
.bind("slider:ready slider:changed", function (event, data) {
var value = $(this)
.nextAll(".output:first")
.html(data.value.toFixed(3));
});
</script>
I want to modify this so that it doesn't create a <span> element and displays the result somewhere else on the page.
So, I would change it to something like the following, but this doesn't work!
<script>
$("[data-slider]")
.each(function () {
var input = $(this);
})
.bind("slider:ready slider:changed", function (event, data) {
var value = $(this);
$(".displayMyValue").html(data.value.toFixed(3));
});
</script>
Could I change the .nextAll to something more appropriate?
My HTML:
<span class="displayMyValue"></span>
<input id="my-input" type="text" value="" data-slider="true" data-slider-range="1000,100000" data-slider-step="100" data-slider-highlight="true" data-slider-theme="volume">
<span class="output">//this created by jQuery//</span>

I'm using this code:
$("[data-slider]").bind("slider:ready slider:changed", function (event, data) {
$(this).next("span").html(data.value.toFixed(0));
});
The bind function searches for the Next span which is used to display the data.
Change the "span" into #IdSpan and it will find the span with the defined ID.

Related

Dynamically adding multiple custom directives associated with single controller in angularjs 1

I have an html template attached to a controller and three directives. There are three buttons. On clicking a button a directive is added to the page(using ng-click) like this(the following is in my controller not in directive):
$scope.addFilterDimension = function() {
console.log('CLICKED!!!!!!!')
var divElement = angular.element(document.querySelector('#filterDimension'));
var appendHtml = $compile('<filter-directive></filter-directive>')($scope);
divElement.append(appendHtml);
}
Similarly for other buttons, other directives are added. Now, I can keep adding as many of these directives as I like, which is the use case here.
These directives are basically like forms containing either dropdowns, input boxes or both. The values user selects from the dropdowns or enters in input boxes have to be sent back to the backend to be stored in the DB.
This is one of the directives(others are very similar):
anomalyApp.directive('filterDirective', function() {
return {
restrict: "E",
scope: {},
templateUrl:'filter-dimension.html',
controller: function($rootScope, $scope, $element) {
$scope.dimensionsOld = $rootScope.dimensionsOld;
$scope.dimensions = $rootScope.dimensions;
$scope.selectedDimensionName = $rootScope.selectedDimensionName;
$scope.selectedDimensionValue = $rootScope.selectedDimensionValue;
$scope.extend = $rootScope.extend;
$scope.selectedExtend = $rootScope.selectedExtend;
$scope.isDateField = $rootScope.isDateField;
console.log($scope.dimensions);
$scope.Delete = function(e) {
//remove element and also destoy the scope that element
$element.remove();
$scope.$destroy();
}
}
}
});
Now, in my controller I assign $rootscope to my values which have to be used in the directives and thus catch them in the directive. Example:
$rootScope.dimensions = temp.map(d=>d.dimName);
$rootScope.selectedDimensionName = '';
$rootScope.selectedDimensionValue = '';
And this is how I retrieve my values from added directives:
var retriveValue = function() {
var filtersData = [];
var constraintsData = [];
var variablesData = [];
var ChildHeads = [$scope.$$childHead];
var currentScope;
while (ChildHeads.length) {
currentScope = ChildHeads.shift();
while (currentScope) {
if (currentScope.dimensions !== undefined){
filtersData.push({
filterDimensionName: currentScope.selectedDimensionName,
filterDimensionValue: currentScope.selectedDimensionValue,
filterDimensionExtend: currentScope.selectedExtend,
filterDimensionIsDateFiled: currentScope.isDateField
});
}
if (currentScope.constraintDimensions !== undefined){
filtersData.push({
constraintDimensionName: currentScope.selectedConstraintName,
constraintDimensionValue: currentScope.selectedConstraintValue,
constraintDimensionExtend: currentScope.selectedConstraintExtend,
constraintDimensionVariable: currentScope.selectedConstraintVariable,
constraintDimensionOperator: currentScope.selectedOperator,
constraintDimensionVariableValue: currentScope.constraintVariableValue,
constraintDimensionIsDateField: currentScope.isDateFieldConstraint
});
}
if (currentScope.variableNames !== undefined){
console.log('currentScope.selectedVariableVariable',currentScope.selectedVariableVariable);
filtersData.push({
variableName: currentScope.selectedVariableVariable,
variableOperator: currentScope.selectedVariableOperator,
variableValue: currentScope.variableVariableValue,
variableExtend: currentScope.selectedVariableExtend
});
}
currentScope = currentScope.$$nextSibling;
}
}
return filtersData;
}
This is one of the directive's template:
<div >
<div>
<label>Dimension</label>
<select class = "custom-select custom-select-lg mb-6" ng-model="selectedDimensionName" ng-options="dimension for dimension in dimensions">
<!-- <option ng-repeat="table in tables track by $index">{{table}}</option> -->
</select>
</div>
<div>
<label>Date Field</label>
<input type="checkbox" ng-model="isDateField">
</div>
<div>
<label>Value</label>
<select multiple class = "custom-select custom-select-lg mb-6" ng-model="selectedDimensionValue" ng-options="val for val in ((dimensionsOld | filter:{'dimName':selectedDimensionName})[0].dimValues)"></select>
</span>
</div>
<div>
<label>Extend</label>
<select class = "custom-select custom-select-lg mb-6" ng-model="selectedExtend" ng-options="val for val in extend"></select>
</span>
</div>
<button type="button" class="btn btn-danger btn-lg" ng-click="Delete($event)">Delete</button>
This is in the main html to add the directive:
<div id="filterDimension"> </div>
I know this is not a good way, but please suggest a better one.
Secondly, a new change has to be made where inside one of the directives there will be a button, clicking on which 2 dropdowns(or simply one more directive) will be added and can be added as many times as needed(just like the other directive).
The issue here is this one is a directive inside another directive and I am facing unusual behavior like:
When I add the parent directive it is fine, I add the child directives its fine, but when I add a second parent and try to add its child, they get appended inside the first directive.
Even if I somehow manage to get out of the above point I do not know how to retrieve values from such directives.
PS: I am new in AngularJS or front-end for that matter, the retriveValue() and using rootscope I got from somewhere online.

Resetting the model values [duplicate]

I have a simple form like so:
<form name="add-form" data-ng-submit="addToDo()">
<label for="todo-name">Add a new item:</label>
<input type="text" data-ng-model="toDoName" id="todo-name" name="todo-name" required>
<button type="submit">Add</button>
</form>
with my controller as follows:
$scope.addToDo = function() {
if ($scope.toDoName !== "") {
$scope.toDos.push(createToDo($scope.toDoName));
}
}
what I'd like to do is clear the text input after submission so I simply clear the model value:
$scope.addToDo = function() {
if ($scope.toDoName !== "") {
$scope.toDos.push(createToDo($scope.toDoName));
$scope.toDoName = "";
}
}
Except now, because the form input is 'required' I get a red border around the form input. This is the correct behaviour, but not what I want in this scenario... so instead I'd like to clear the input and then blur the input element. Which leads me to:
$scope.addToDo = function() {
if ($scope.toDoName !== "") {
$scope.toDos.push(createToDo($scope.toDoName));
$scope.toDoName = "";
$window.document.getElementById('todo-name').blur();
}
}
Now, I know that modifying the DOM from the controller like this is frowned upon in the Angular documentation - but is there a more Angular way of doing this?
When you give a name to your form it automatically gets added to the $scope.
So if you change your form name to "addForm" ('cause I don't think add-from is a valid name for angular, not sure why), you'll have a reference to $scope.addForm.
If you use angular 1.1.1 or above, you'll have a $setPristine() method on the $scope.addForm. which should recursively take care of resetting your form. or if you don't want to use the 1.1.x versions, you can look at the source and emulate it.
For those not switching over to 1.1.1 yet, here is a directive that will blur when a $scope property changes:
app.directive('blur', function () {
return function (scope, element, attrs) {
scope.$watch(attrs.blur, function () {
element[0].blur();
});
};
});
The controller must now change a property whenever a submit occurs. But at least we're not doing DOM manipulation in a controller, and we don't have to look up the element by ID:
function MainCtrl($scope) {
$scope.toDos = [];
$scope.submitToggle = true;
$scope.addToDo = function () {
if ($scope.toDoName !== "") {
$scope.toDos.push($scope.toDoName);
$scope.toDoName = "";
$scope.submitToggle = !$scope.submitToggle;
}
};
}
HTML:
<input type="text" data-ng-model="toDoName" name="todo-name" required
blur="submitToggle">
Plnkr
I have made it work it as below code.
HTML SECTION
<td ng-show="a">
<input type="text" ng-model="e.FirstName" />
</td>
Controller SECTION
e.FirstName= '';

Adding Text Box to Angular Form

I'm trying to dynamically add a textbox to an Angular form. I'm using ng-repeat and I can add the text box easily by just pushing, an empty string to the array. It will add another textbox, the problem is that ng-model is not syncing the data, and when text is added it remains an empty string.
The text boxes that get created from the initial array sync just fine, it's just the newly added text boxes that are not working.
I've been looking around and one suggestion I saw was to always use a "." when using ng-model, but that didn't work for me.
<div ng-repeat="text in image.text track by $index">
<md-input-container class="md-block" novalidate>
<label>Text {{$index + 1}}:</label>
<textarea md-maxlength="2500" md-midlength="1" required md-no-asterisk name="text"
placeholder="{{text}}"
ng-model="text"></textarea>
</md-input-container>
</div>
Controller:
(function () {
'use strict';
angular
.module('app.article')
.controller('ArticleEditController', ArticleEditController);
ArticleEditController.$inject= ['articleEditDataService', '$routeParams', '$log'];
function ArticleEditController(articleEditDataService, $routeParams, $log) {
var vm = this;
 var site = $routeParams.site;
var articleName = $routeParams.article;
var articleRevision_id = $routeParams.revision_id;
vm.data = {};
vm.addNewText = addNewText;
vm.removeText = removeText;
vm.saveArticle = saveArticle;
vm.numMessage = 1;
activate();
function activate(){
getArticle();
}
function getArticle(){
var data = articleEditDataService.getArticle(site, articleName, articleRevision_id);
data.then(function successResponse(res) {
vm.data = res.results.data;
}, function errorResponse (res) {
console.log(res);
});
}
function saveArticle(){
var article = articleEditDataService.postArticle(vm.data, site, articleName, articleRevision_id);
console.log(vm.data);
article
.then(updateArticleSuccess)
.catch(updateArticleError);
}
function updateArticleSuccess(message){
$log.info(message);
}
function updateArticleError(errorMessage){
$log.error(errorMessage);
}
function addNewText (index, key) {
vm.data.content.image_sets[key].text.push("");
}
function removeText (index, key) {
if(vm.data.content.image_sets[key].text.length > 1){
vm.data.content.image_sets[key].text.pop();
}
}
};
})();
initialize the model variable within your controller as an empty object.
then within your text input your ng-model="model[$index]".

update angularjs model from jquery [duplicate]

I have this simple scenario:
Input element which value is changed by jQuery's val() method.
I am trying to update the angular model with the value that jQuery set. I tried to write a simple directive, but it's not doing what I want.
Here's the directive:
var myApp = angular.module('myApp', []);
myApp.directive('testChange', function() {
return function(scope, element, attrs) {
element.bind('change', function() {
console.log('value changed');
})
}
})
this is the jQuery part:
$(function(){
$('button').click(function(){
$('input').val('xxx');
})
})
and html:
<div ng-app="myApp">
<div ng-controller="MyCtrl">
<input test-change ng-model="foo" />
<span>{{foo}}</span>
</div>
</div>
<button>clickme</button>
Here is the fiddle with my try:
http://jsfiddle.net/U3pVM/743/
Can someone please point me in the right direction?
ngModel listens for "input" event, so to "fix" your code you'd need to trigger that event after setting the value:
$('button').click(function(){
var input = $('input');
input.val('xxx');
input.trigger('input'); // Use for Chrome/Firefox/Edge
input.trigger('change'); // Use for Chrome/Firefox/Edge + IE11
});
For the explanation of this particular behaviour check out this answer that I gave a while ago: "How does AngularJS internally catch events like 'onclick', 'onchange'?"
But unfortunately, this is not the only problem you have. As pointed out with other post comments, your jQuery-centric approach is plain wrong. For more info take a look at this post: How do I “think in AngularJS” if I have a jQuery background?).
Hope this is useful for someone.
I was unable to get the jQuery('#myInputElement').trigger('input') event to be picked up my angular app.
I was however, able to get angular.element(jQuery('#myInputElement')).triggerHandler('input') to be picked up.
The accepted answer which was triggering input event with jQuery didn't work for me. Creating an event and dispatching with native JavaScript did the trick.
$("input")[0].dispatchEvent(new Event("input", { bubbles: true }));
I don't think jQuery is required here.
You can use $watch and ng-click instead
<div ng-app="myApp">
<div ng-controller="MyCtrl">
<input test-change ng-model="foo" />
<span>{{foo}}</span>
<button ng-click=" foo= 'xxx' ">click me</button>
<!-- this changes foo value, you can also call a function from your controller -->
</div>
</div>
In your controller :
$scope.$watch('foo', function(newValue, oldValue) {
console.log(newValue);
console.log(oldValue);
});
You have to use the following code in order to update the scope of the specific input model as follows
$('button').on('click', function(){
var newVal = $(this).data('val');
$('select').val(newVal).change();
var scope = angular.element($("select")).scope();
scope.$apply(function(){
scope.selectValue = newVal;
});
});
I made modifications on only controller initialization by adding listener on action button:
$(document).on('click', '#action-button', function () {
$timeout(function () {
angular.element($('#input')).triggerHandler('input');
});
});
Other solutions did not work in my case.
I know it's a bit late to answer here but maybe I may save some once's day.
I have been dealing with the same problem. A model will not populate once you update the value of input from jQuery. I tried using trigger events but no result.
Here is what I did that may save your day.
Declare a variable within your script tag in HTML.
Like:
<script>
var inputValue="";
// update that variable using your jQuery function with appropriate value, you want...
</script>
Once you did that by using below service of angular.
$window
Now below getData function called from the same controller scope will give you the value you want.
var myApp = angular.module('myApp', []);
app.controller('imageManagerCtrl',['$scope','$window',function($scope,$window) {
$scope.getData = function () {
console.log("Window value " + $window.inputValue);
}}]);
I've written this little plugin for jQuery which will make all calls to .val(value) update the angular element if present:
(function($, ng) {
'use strict';
var $val = $.fn.val; // save original jQuery function
// override jQuery function
$.fn.val = function (value) {
// if getter, just return original
if (!arguments.length) {
return $val.call(this);
}
// get result of original function
var result = $val.call(this, value);
// trigger angular input (this[0] is the DOM object)
ng.element(this[0]).triggerHandler('input');
// return the original result
return result;
}
})(window.jQuery, window.angular);
Just pop this script in after jQuery and angular.js and val(value) updates should now play nice.
Minified version:
!function(n,t){"use strict";var r=n.fn.val;n.fn.val=function(n){if(!arguments.length)return r.call(this);var e=r.call(this,n);return t.element(this[0]).triggerHandler("input"),e}}(window.jQuery,window.angular);
Example:
// the function
(function($, ng) {
'use strict';
var $val = $.fn.val;
$.fn.val = function (value) {
if (!arguments.length) {
return $val.call(this);
}
var result = $val.call(this, value);
ng.element(this[0]).triggerHandler('input');
return result;
}
})(window.jQuery, window.angular);
(function(ng){
ng.module('example', [])
.controller('ExampleController', function($scope) {
$scope.output = "output";
$scope.change = function() {
$scope.output = "" + $scope.input;
}
});
})(window.angular);
(function($){
$(function() {
var button = $('#button');
if (button.length)
console.log('hello, button');
button.click(function() {
var input = $('#input');
var value = parseInt(input.val());
value = isNaN(value) ? 0 : value;
input.val(value + 1);
});
});
})(window.jQuery);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div ng-app="example" ng-controller="ExampleController">
<input type="number" id="input" ng-model="input" ng-change="change()" />
<span>{{output}}</span>
<button id="button">+</button>
</div>
If you are using IE, you have to use: input.trigger("change");
add .change() after setting the value.
example:('id').val.('value').change();
also don't forget to add onchange or ng-change tag in html
I did this to be able to update the value of ngModel from the outside with Vanilla/jQuery:
function getScope(fieldElement) {
var $scope = angular.element(fieldElement).scope();
var nameScope;
var name = fieldElement.getAttribute('name');
if($scope) {
if($scope.form) {
nameScope = $scope.form[name];
} else if($scope[name]) {
nameScope = $scope[name];
}
}
return nameScope;
}
function setScopeValue(fieldElement, newValue) {
var $scope = getScope(fieldElement);
if($scope) {
$scope.$setViewValue(newValue);
$scope.$validate();
$scope.$render();
}
}
setScopeValue(document.getElementById("fieldId"), "new value");
Not what OP asked, but for any soul that might be as well writing an userscript that goes through input fields and fills the required details. Nothing (fully) worked for me, but finally managed to get it done this way:
var el = $('#sp_formfield_fw_ip');
el.val("some value");
angular.element(el).triggerHandler('focus');
angular.element(el).triggerHandler('input');
angular.element(el).triggerHandler('change');
angular.element(el).triggerHandler('blur');
Open developer tools, and inspect input field for added events. There I found all of them (in my case): focus, input, change and blur.

Angular - clear form input after submit

I have a simple form like so:
<form name="add-form" data-ng-submit="addToDo()">
<label for="todo-name">Add a new item:</label>
<input type="text" data-ng-model="toDoName" id="todo-name" name="todo-name" required>
<button type="submit">Add</button>
</form>
with my controller as follows:
$scope.addToDo = function() {
if ($scope.toDoName !== "") {
$scope.toDos.push(createToDo($scope.toDoName));
}
}
what I'd like to do is clear the text input after submission so I simply clear the model value:
$scope.addToDo = function() {
if ($scope.toDoName !== "") {
$scope.toDos.push(createToDo($scope.toDoName));
$scope.toDoName = "";
}
}
Except now, because the form input is 'required' I get a red border around the form input. This is the correct behaviour, but not what I want in this scenario... so instead I'd like to clear the input and then blur the input element. Which leads me to:
$scope.addToDo = function() {
if ($scope.toDoName !== "") {
$scope.toDos.push(createToDo($scope.toDoName));
$scope.toDoName = "";
$window.document.getElementById('todo-name').blur();
}
}
Now, I know that modifying the DOM from the controller like this is frowned upon in the Angular documentation - but is there a more Angular way of doing this?
When you give a name to your form it automatically gets added to the $scope.
So if you change your form name to "addForm" ('cause I don't think add-from is a valid name for angular, not sure why), you'll have a reference to $scope.addForm.
If you use angular 1.1.1 or above, you'll have a $setPristine() method on the $scope.addForm. which should recursively take care of resetting your form. or if you don't want to use the 1.1.x versions, you can look at the source and emulate it.
For those not switching over to 1.1.1 yet, here is a directive that will blur when a $scope property changes:
app.directive('blur', function () {
return function (scope, element, attrs) {
scope.$watch(attrs.blur, function () {
element[0].blur();
});
};
});
The controller must now change a property whenever a submit occurs. But at least we're not doing DOM manipulation in a controller, and we don't have to look up the element by ID:
function MainCtrl($scope) {
$scope.toDos = [];
$scope.submitToggle = true;
$scope.addToDo = function () {
if ($scope.toDoName !== "") {
$scope.toDos.push($scope.toDoName);
$scope.toDoName = "";
$scope.submitToggle = !$scope.submitToggle;
}
};
}
HTML:
<input type="text" data-ng-model="toDoName" name="todo-name" required
blur="submitToggle">
Plnkr
I have made it work it as below code.
HTML SECTION
<td ng-show="a">
<input type="text" ng-model="e.FirstName" />
</td>
Controller SECTION
e.FirstName= '';

Resources