I have an issue with jsviews. I want to bind an array of elements. Each element is an object. Elements are added dynamicaly. Value of one field of each element computes base on another field. How is it posiible to do without refreshing array every time?
js:
model = {
elements: []
};
$(function() {
$.when($.templates('#tmpl').link('#container', model)
.on('click', '#addElement', function () {
$.observable(model.elements).insert({});
})
).done(function() {
$.observe(model, 'elements', function(e, eventArgs) {
if (eventArgs.change === 'insert') {
eventArgs.items.forEach(function(addedElement) {
$.observe(addedElement, 'value1', function(e) {
var element = e.target;
element.value2 = 'Value1 is ' + element.value1;
$.observable(element).setProperty('value2', element.value2);
$.observable(model).setProperty('recent', element.value1);
});
});
}
});
});
});
html:
<div id="container"></div>
<script id="tmpl" type="text/x-jsrender">
<input id="addElement" type="button" value="add new element"/>
<div id="box">
{^{for elements tmpl="#elementTmpl"/}}
</div>
<input type="text" data-link="recent" />
</script>
<script id="elementTmpl" type="text/x-jsrender">
<div>
<input name="input1" data-link="value1" />
<input name="input2" data-link="value2" />
</div>
</script>
I created jsfiddle that illustrates the problem.
You can use ObserveAll(): http://www.jsviews.com/#observeAll.
Every time the element.value1 changes, you update the calculated properties element.value2 and model.recent.
I updated your fiddle here https://jsfiddle.net/1rjgh2sn/2/ with the following:
$.templates('#tmpl').link('#container', model)
.on('click', '#addElement', function () {
$.observable(model.elements).insert({});
});
$.observable(model).observeAll(function(e, eventArgs) {
if (eventArgs.change === "set" && eventArgs.path === "value1") {
var element = e.target;
$.observable(element).setProperty('value2', 'Value1 is ' + element.value1);
$.observable(model).setProperty('recent', element.value1);
}
});
Related
I have a form and when I click on the button I have to copy but it doesn't work. Even if it works I can't copy the functionality of the form.I tried to copy to generic form but it doesn't work
JQ:
$(document).ready(function() {
var addToWishList = document.querySelector('#add-to-wishlist');
var wishlistItem = document.querySelector('#wishlist-item');
var wishlist = document.querySelector('#wishlist');
var clearlist = document.querySelector('#clearlist');
var saved = localStorage.getItem('wishlistItems');
var add = document.querySelector('#eventBtn');
addToWishList.addEventListener('submit', function (event) {
event.preventDefault();
if (wishlistItem.value.length < 1) return;
wishlist.innerHTML += '<li>' + wishlistItem.value + '</li>';
localStorage.setItem('wishlistItems', wishlist.innerHTML);
}, false);
if (saved) {
wishlist.innerHTML = saved;
}
$(document).ready(function(){
$("#clearlist").click(function() {
localStorage.clear();
$("#list li").empty();
});
});
add.click(function(){
addToWishList.clone(true).appendTo("body");
});
});
And my form:
<form id="add-to-wishlist">
<button type="button" id="eventBtn">Add new list</button>
<label><h1>To do list</h1></label>
<input type="text" name="wishlist-item" id="wishlist-item">
<button type="submit">Add to Wishlist</button>
<button type="reset" id="clearlist">Delete records</button>
<ul id="list">
<li id="wishlist"></li>
</ul>
</form>
``
There are 2 issues with your approach:
1) ids have to be unique, otherwise your HTML isn't valid and won't work as expected. It's better to change to classes instead. Otherwise it would be necessary to e.g. increment a value each time you clone the form and change all ids of the cloned elements accordingly.
2) To set any event on a dynamically created element, it's necessary to delegate this event from an already existing parent element of this element that's already there when the page is initially loaded, e.g. from document.
I adjusted your code accordingly and adjusted the events to work with the specific form. The code isn't working in a stack snippet here because of the local storage, but here's a working Fiddle.
$(document).ready(function() {
var saved = localStorage.getItem('wishlistItems');
$(document).on("click", ".add", function(event) {
event.preventDefault();
let wishlistItem = $(this).closest("form").find(".wishlist-item");
let wishlist = $(this).closest("form").find(".wishlist");
if (wishlistItem.val().length < 1) return;
wishlist.append('<li>' + wishlistItem.val() + '</li>');
localStorage.setItem('wishlistItems', wishlist.html());
});
if (saved) {
$(".wishlist:eq(0)").html(saved);
}
$(document).on("click", ".clearlist", function() {
localStorage.clear();
$(this).closest("form").find(".list li").remove();
});
$(document).on("click", ".eventBtn", function() {
let newList = $(this).closest("form").clone();
newList.find(".list li").empty();
newList.find(".wishlist-item").empty();
newList.appendTo("body")
});
});
<form class="add-to-wishlist">
<button type="button" class="eventBtn">Add new list</button>
<label>
<h1>To do list</h1>
</label>
<input type="text" name="wishlist-item" class="wishlist-item">
<button class="add">Add to Wishlist</button>
<button type="reset" class="clearlist">Delete records</button>
<ul class="list">
<li class="wishlist"></li>
</ul>
</form>
In a for loop based on divs count I need to select each div child so I got to get the id of the div.
this is what I have tried:
var json = [{
'orderId': order,
'attributes': [],
'services': []
}];
var divLength = $('#stepchild div').length;
for (i = 0; i < divLength; i++) {
var fields = {};
$('#divID input').each(function() {
fields[this.name] = $(this).val();
})
$('#divID select').each(function() {
fields[this.name] = $(this).val();
})
json[0]['attributes'].push(fields);
}
<div id="form0">
<input type="text" class="field1">
</div>
<div id="form1">
<input type="text" class="field1">
</div>
<div id="form2">
<input type="text" class="field1">
</div>
You can use a loop like this (basic example):
$('div').each(function()
{
console.log($(this).attr('id'))
})
refs:
https://api.jquery.com/attr/
https://api.jquery.com/jQuery.each/
$('target').each(function()
{
console.log($(this).attr('id'))
});
this will run for each target match . in your case 'div' is your target . you can use find , child attribute for sub search
Welcome to Stack Overflow
You need to use map function here in order to collect ID or value inside the textbox.
Here is an example to get ID:
var json = [{
'orderId': 'order',
'attributes': [],
'services': []
}];
function getDivID()
{
var values = $("#stepchild div").map(function (i, e) {
return $(e).attr('id');
}).get();
json[0]['attributes'].push(values);
console.log("json[0]['attributes'] is now : " + json[0]['attributes']);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="stepchild">
<div id="form0">
<input type="text" class="field1">
</div>
<div id="form1">
<input type="text" class="field1">
</div>
<div id="form2">
<input type="text" class="field1">
</div>
</div>
<button onclick="getDivID()">Click here to get div ID</button>
Using .map() function you can also collect value form each element inside div :
var json = [{
'orderId': 'order',
'attributes': [],
'services': []
}];
function getValue() {
var values = $("#stepchild input").map(function (i, e) {
return $(e).val();
}).get();
json[0]['attributes'].push(values);
console.log("json[0]['attributes'] is now : " + json[0]['attributes']);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="stepchild">
<div id="form0">
<input type="text" class="field1" value="abc">
</div>
<div id="form1">
<input type="text" class="field1" value="xyz">
</div>
<div id="form2">
<input type="text" class="field1" value="something">
</div>
</div>
<button onclick="getValue()">Click here to get value</button>
refs:
http://api.jquery.com/map/
Disclaimer : I know the question is about jquery, but I would like to provide the non-jQuery version :
If you just want the IDs in a list, you can use this :
[...document.querySelectorAll('div')].map(div => div.id)
Or if you need to loop over them and do some processing for each, you can use this :
[...document.querySelectorAll('div')].forEach(div => {
// process the div element here with div.id beeing the ID
});
Within $.fn.each, you can access the current element id with this.id or with the parameter element.id.
Keep in mind that $() will give you a collection. You can write your code like this:
const json = [{
'orderId': order,
'attributes': [],
'services': [],
}];
$('#stepchild div').each(function (index, element) {
let fields = {};
$(element).find('input, select').each(function () {
fields[this.name] = $(this).val();
});
json[0]['attributes'].push(fields);
});
I am setting an element's data attribute onclick of it to the current index, of the element... for example, take the following html:
<ul>
<li class="get-me">
Click Me <input type="text" value="" name="name1" />
</li>
<li class="get-me">
Click Me <input type="text" value="" name="name2" />
</li>
<li class="not-me">
<input type="text" value="A value" name="aName" readonly />
</li>
<li class="get-me">
Click Me <input type="text" value="" name="name3" />
</li>
</ul>
Now, onclick, of the a.alink links I add data('index') to each input sibling... example:
jQuery(document).ready(function($) {
$('.alink').on('click', function(event) {
event.preventDefault();
var $this = $(this),
$input = $this.next('input');
if ($input.length)
{
$('.alink').each(function(i, obj) {
if (obj == $this.eq(0))
{
$(obj).next('input').data('index', i);
return false;
}
});
}
});
});
Now the order of these li's can change, after the links have been clicked on, but the jQuery.data stays the same, so wondering if it's possible to get input element that has .data('index') == 1 somehow, as a jQuery object element (like $(this))? I know that it's possible if the data attribute existed, but this is not the case as it's being set in code instead. And I'm wondering if this can be selected directly instead of looping through all input elements and checking their .data('index') properties.
EDIT
So I have split this into a function here:
function inputFilter(selector, index)
{
var obj = null;
if (selector.trim() !== '')
{
obj = $(selector).filter(function() {
return $(this).data('index') == index;
});
}
return obj;
}
But trying to use it returns all input elements:
var $object = inputFilter('input', 1);
What am I doing wrong?
Use a .filter function that looks for the data you want.
$('input').filter(function() {
return $(this).data('index') == '1';
});
function inputFilter(selector, index) {
var obj = null;
if (selector.trim() !== '') {
obj = $(selector).filter(function() {
return $(this).data('index') == index;
});
}
return obj;
}
$("#input1").data("index", 1);
$("#input2").data("index", 3);
console.log(inputFilter('input', 1).map(function() {
return this.id;
}).get());
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="input1">
<input id="input2">
<input id="input3">
If I change the value of an input field programmatically, the input and change events are not firing. For example, I have this scenario:
var $input = $('#myinput');
$input.on('input', function() {
// Do this when value changes
alert($input.val());
});
$('#change').click(function() {
// Change the value
$input.val($input.val() + 'x');
});
<input id="myinput" type="text" />
<button id="change">Change value</button>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
The problem: The event is triggered when I type in the textfield, but not when I press the button. Is there a way to achieve this with some kind of event or otherwise without having to do it manually?
What I don't want to do: I could go through all my code to add a trigger or function call everywhere manually, but that's not what I'm looking for.
Why: The main reason I would like to do this automatically is that I have a lot of input fields and a lot of different places where I change these inputs programmatically. It would save me a lot of time if there was a way to fire the event automatically when any input is changed anywhere in my code.
Simple solution:
Trigger input after you call val():
$input.trigger("input");
var $input = $("#myinput");
$input.on('input', function() {
alert($(this).val());
});
$('#change').click(function() {
// Change the value and trigger input
$input.val($input.val() + 'x').trigger("input");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input id="myinput" type="text" />
<button id="change">Change value</button>
Specific solution:
As mentioned you don't want to trigger input manually. This solution triggers the event automatically by overriding val().
Just add this to your code:
(function ($) {
var originalVal = $.fn.val;
$.fn.val = function (value) {
var res = originalVal.apply(this, arguments);
if (this.is('input:text') && arguments.length >= 1) {
// this is input type=text setter
this.trigger("input");
}
return res;
};
})(jQuery);
See JSFiddle Demo
PS
Notice this.is('input:text') in the condition. If you want to trigger the event for more types, add them to the condition.
There are some ways on how to achieve it. Here, you can use the levelup HTML's oninput() event that occurs immediately when an element is changed and call the function.
<input id="myinput" type="text" oninput="sample_func()" />
<button id="change">Change value</button>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
.
var input = $("#myinput");
function sample_func(){
alert(input.val());
}
$('#change').click(function() {
input.val(input.val() + 'x');
});
Or this jQuery, input thing (just related to above example).
<input id="myinput" type="text" />
<button id="change">Change value</button>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
.
var input = $("#myinput");
input.on("input", function() {
alert(input.val());
});
$('#change').click(function() {
input.val(input.val() + 'x');
});
You can also use javascript setInterval() which constantly runs with a given interval time. It's only optional and best if you're doing time-related program.
<input id="myinput" type="text" />
<button id="change">Change value</button>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
.
var input = $("#myinput");
setInterval(function() { ObserveInputValue(input.val()); }, 100);
$('#change').click(function() {
input.val(input.val() + 'x');
});
jQuery listeners only work on actual browser events and those aren't thrown when you change something programmatically.
You could create your own miniature jQuery extension to proxy this so that you always trigger the event but only have to do in one modular place, like so:
$.fn.changeTextField = function (value) {
return $(this).val(value).trigger("change");
}
Then, just call your new function whenever you want to update your text field, instead of using jQuery's 'val' function:
$("#myInput").changeTextField("foo");
Here's a version working with a proxy function:
<!DOCTYPE html>
<html>
<head>
<title>Test stuff</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
</head>
<body>
<input id="myInput" type="text" />
<button id="myButton">Change value</button>
<script type="text/javascript">
$.fn.changeTextField = function (value) {
return $(this).val(value).trigger("change");
}
$( document ).ready(function() {
var $input = $("#myInput");
$input.on("change", function() {
alert($input.val());
});
$('#myButton').click(function() {
$("#myInput").changeTextField("foo");
});
});
</script>
</body>
</html>
For reference, this question has really already been answered here:
Why does the jquery change event not trigger when I set the value of a select using val()?
and here: JQuery detecting Programatic change event
Looks like there's no way, other than using .trigger().
Let's try the same thing using .change() event:
var $input = $("#myinput");
$input.on('change paste keyup', function() {
alert($(this).val());
});
$('#change').click(function() {
$input.val($input.val() + 'x').trigger("change");
});
<input id="myinput" type="text" />
<button id="change">Change value</button>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Or you need to trigger it manually:
$('#change').click(function() {
$input.val($input.val() + 'x').trigger("input");
});
Snippet
var $input = $("#myinput");
$input.on('input', function() {
alert($(this).val());
});
$('#change').click(function() {
$input.val($input.val() + 'x').trigger("input");
});
<input id="myinput" type="text" />
<button id="change">Change value</button>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Trigger didn't work for. Creating an event and dispatching with native JavaScript did the work.
Source: https://stackoverflow.com/a/41593131/6825339
<script type="text/javascript">
$.fn.changeTextField = function (value) {
return $(this).val(value).dispatchEvent(new Event("input", { bubbles: true });
}
$( document ).ready(function() {
var $input = $("#myInput");
$input.on("change", function() {
alert($input.val());
});
$('#myButton').click(function() {
$("#myInput").changeTextField("foo");
});
});
</script>
var $input = $('#myinput');
$input.on('input', function() {
// Do this when value changes
alert($input.val());
});
$('#change').click(function() {
// Change the value
$input.val($input.val() + 'x');
});
<input id="myinput" type="text" />
<button id="change">Change value</button>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
$input.val($input.val() + 'x')
$input.trigger('change');
The change event only fire when input blur.
Try this
$('#input').trigger('change');
i want to add element to div in angularjs. so write this code but not work correctly. thanks for your help :)
function TestController($scope) {
$scope.addElement = function(){
var myElements = angular.element(document.querySelector('#form'));
console.log(myElements);
if(myElements.length == 0)
alert("Not Find");
else
myElements.prepend( myElements[0].children[1]);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app ng-controller="TestController" id="form">
<input type="button" ng-click="addElement()" value="add"></input>
<div id="div">
<input type="text" name="name">
</div>
</div>
Here is what I have tried.
$scope.addElement = function(){
var myElements = angular.element(document.querySelector('#form'));
console.log(myElements)
console.log(myElements[0].children[1])
if(myElements.length == 0)
alert("Not Find");
else{
html = angular.element(myElements[0].children[1]).clone();
myElements.append( html);
}
You should use angular clone method.
EDIT.
Here it the Plunker
If I understood your question correctly, you want to append an input element to div on each ng-click?
You just need to target the div with jquery and append the element with it.
See example: http://jsbin.com/seyawemijo/edit?html,js,output
Often than not when you want to modify the DOM directly, there is a way to do it without.
"Thinking in Angular way"
function TestController($scope) {
$scope.textArr = [];
var count = 1;
$scope.addElement = function() {
var ele = {
model: 'hello ' + count++
}
$scope.textArr.push(ele);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app ng-controller="TestController" id="form">
<input type="button" ng-click="addElement()" value="add" />
<div ng-repeat="text in textArr">
<input type="text" ng-model="text.model">
</div>
<div>{{textArr}}</div>
</div>
Try this one
myElements.prepend(myElements[0].children[1].value);
I have altered the above solution to add other attributes(including id) to the input text element
var globalCntr = 0;
function TestController($scope) {
$scope.addElement = function() {
globalCntr ++;
$('<input>',{
type:'text',
id:('inputText'+globalCntr)
}).appendTo($('#target'));
};
}