I want to select object from ng-repeat list and insert it in a array, then display each attribute of the selected object in a form. My problem is that I can not insert the object in array, but able to select it. I have narrowed down error. The checkList array is always empty no matter how frontend interface interacts with it(click on checkbox). I have no idea what cause this issue?
My code:
In product.view.html:
<h1>Welcome!</h1>
<p>You're in Product profolio!!</p>
<h3>All Products:</h3>
<ul>
<li ng-repeat="product in vm.allProducts track by $index">
{{product.id}} -- {{product.product_name}} -- {{product.product_image}} -- {{product.category}} -- {{product.published_time}} -- {{product.store_id}}
<input type="checkbox" ng-model="bool" ng-change = "vm.sync(bool,product)"> {{bool}}
</li>
</ul>
{{vm.checkList}}
<form novalidate class="simple-form">
Product Name: <input type="text" ng-model="vm.checkList[0].product_name" /><br />
product_image: <input type="text" ng-model="vm.checkList[0].product_image" /><br />
Category: <input type="text" ng-model="vm.checkList[0].category" /><br />
publish time: <input type="text" ng-model="vm.checkList[0].published_time" /><br />
store ID: <input type="number" ng-model="vm.checkList[0].store_id" /><br />
</form>
- <button ng-click="vm.createProduct(vm.checkList)">Create</button>
- <button ng-click="vm.updateProduct(vm.checkList)">Update</button>
- <button ng-click="vm.deleteProduct(vm.checkList.id)">Delete</button>
<p> </p>
<p>Logout</p>
In productController.js:
(function () {
'use strict';
angular
.module('app')
.controller('ProductController', ProductController);
ProductController.$inject = ['UserService', '$rootScope'];
function ProductController(UserService, $rootScope) {
var vm = this;
vm.allProducts = [];
vm.checkList = [];
vm.deleteProduct = deleteProduct;
vm.createProduct = createProduct;
vm.updateProduct = updateProduct;
vm.isChecked = isChecked;
vm.sync = sync;
initController();
function initController() {
loadAllProduct();
}
function loadCurrentProduct(productname) {
UserService.GetByUsername(username)
.then(function (product) {
vm.product = product;
});
}
function loadAllProduct() {
var url = 'http://127.0.0.1:8000/products';
UserService.GetAll(url)
.then(function (products) {
vm.allProducts = products;
});
}
function deleteProduct(id) {
var url = 'http://127.0.0.1:8000/products/';
UserService.Delete(url,id)
.then(function () {
console.log('flash page!')
loadAllProduct();
console.log('done!')
});
}
function createProduct(product){
var url = 'http://127.0.0.1:8000/products';
UserService.Create(url,product)
.then(function(){
console.log('has creaet product!')
loadAllProduct();
console.log('done!')
});
}
function updateProduct(product){
var url = 'http://127.0.0.1:8000/products/';
UserService.Update(url,product)
.then(function(){
console.log('has upadte product!')
loadAllProduct();
console.log('done!')
});
}
function sync(bool,product){
console.log("get into sync!");
console.log(bool);
if(bool)
{
vm.checkList.push[product];
console.log(vm.checkList);
console.log(product);
}
else
{
for(var i=0; i < vm.checkList.length; i++)
{
if(vm.checkList[i].id == product.id)
{
vm.checkList.splice(i,1);
}
}
}
}
}
})();
My page:
My error shows in console:
Related
I am trying to create simple knockout example using module pattern
var login = {}; //login namespace
//Constructor
login.UserData = function () {
var self = this;
self.UserName = ko.observable("");
self.Password = ko.observable("");
};
//View-Model
login.UserVM = function () {
this.userdata = new login.UserData(),
this.apiUrl = 'http://localhost:9090/',
this.authenticate = function () {
var data = JSON.parse(ko.toJSON(this.userdata));
var service = apiUrl + '/api/Cryptography/Encrypt';
DBconnection.fetchdata('POST', service, JSON.stringify(data.Password), response, function () { console.log('Cannot fetch data') }, null, true);
function response(res) {
console.log(res)
}
}
return {
authenticate: this.authenticate
}
}();
$(function () {
ko.applyBindings(login.UserVM); /* Apply the Knockout Bindings */
});
HTML CODE:
<form id="loginform" name="loginForm" method="POST">
<div id="form-root">
<div>
<label class="form-label">User Name:</label>
<input type="text" id="txtFirstName" name="txtFirstName" data-bind="value:login.UserData.UserName" />
</div>
<div>
<label class="form-label">Password:</label>
<input type="text" id="txtLastName" name="txtLastName" data-bind="value:login.UserData.Password" />
</div>
<div>
<input type="button" id="btnSubmit" value="Submit" data-bind="click: authenticate" />
</div>
</div>
</form>
the problem is am not able to get userdata in the viewmodel on click of submit it is returning undefined and the login object holds the changed value of textbox but on click it is returning black values.
please let me know
Also can you let me know how to implement definative module pattern in the same code.
The object you are returning from login.UserVM has only authenticate property and doesn't have userdata or apiUrl properties. So, instead using an IIFE to create an object, set login.UserVM to a constructor function similar to login.UserData. And then use new operator to create the viewModel object. Now the viewModel will have userdata and apiUrl properties (remove the return from the function)
Also, you need to change the HTML bindings to: data-bind="value:userdata.UserName". This looks for the userdata property inside the bound viewModel
var login = {}; //login namespace
//Constructor
login.UserData = function () {
var self = this;
self.UserName = ko.observable("");
self.Password = ko.observable("");
};
//View-Model
login.UserVM = function () {
this.userdata = new login.UserData(),
this.apiUrl = 'http://localhost:9090/',
this.authenticate = function () {
var data = JSON.parse(ko.toJSON(this.userdata));
console.log(data)
//var service = this.apiUrl + '/api/Cryptography/Encrypt';
//DBconnection.fetchdata('POST', service, JSON.stringify(data.Password), response, function () { console.log('Cannot fetch data') }, null, true);
function response(res) {
console.log(res)
}
}
}; // remove the () from here
ko.applyBindings(new login.UserVM()); /* Apply the Knockout Bindings */
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<form id="loginform" name="loginForm" method="POST">
<div id="form-root">
<div>
<label class="form-label">User Name:</label>
<input type="text" id="txtFirstName" name="txtFirstName" data-bind="value:userdata.UserName" />
</div>
<div>
<label class="form-label">Password:</label>
<input type="text" id="txtLastName" name="txtLastName" data-bind="value:userdata.Password" />
</div>
<div>
<input type="button" id="btnSubmit" value="Submit" data-bind="click: authenticate" />
</div>
</div>
</form>
I have this below code. I can display the list of JSON file but I can't click the items of the list. Could you teach me How to add click and store item function.
What I would like to do is click the item of the list .After click it "NAME" value store the textbox. so then After set the value Click submit buttom then pass the NAME and related data. For example. Fist data https://api.myjson.com/bins/8x0ag
Fist data name is orange. When user click the orange. and press submit button I would like to send the code "102" and location "N34" data to Next page.
name "orange"
code "102"
location "N34"
Actually I had another code. To select item and store the value into the text field. but I changed the code after that I lost selecting function.
$(document).ready(function() {
Main.init();
});
var Main = (function($) {
return {
vars: { },
init: function() {
Main.build();
Main.events();
},
events: function() {
$(document).on('keyup', '.search', function() {
const ref = $(this).attr('data-ref');
const {
vars
} = Main;
$(`.resultUl[data-ref="${ref}"]`).html('');
const searchField = $(this).val();
const expression = new RegExp(searchField, "i");
$.each(vars.JSONdata, (key, value) => {
const {
name,
location,
code,
image
} = value;
if (name.search(expression) != -1 || location.search(expression) != -1) {
$(`.resultUl[data-ref="${ref}"]`).append(
`<li class="list-group-item link-class"
data-name="${name}"
data-code="${code}"
data-location="${location}">
<img src="${image}" height="40" width="40" class="img-thumbnail" />
${name}
<span class="text-muted">${location}</span>
</li>`
);
}
});
});
},
build: async function() {
JSONdata = await this.getJson();
this.vars = {
JSONdata
};
this.generateFields(20);
},
getJson: () => new Promise((resolve, reject) => {
$.getJSON('https://api.myjson.com/bins/8x0ag', (data) => {
resolve(data);
}).fail(function() {
reject([]);
})
}),
generateFields: (fieldNumber) => {
Array(fieldNumber).fill().map((v, i) => {
const ref = i + 1;
$('#container').append(
`<div class="fieldContainer">
<div class="btn-group">
<input type="text" class="search" data-ref="${ref}" placeholder="" class="form-control" size="3000" onkeypress="return event.keyCode!=13" />
<span class="searchclear glyphicon glyphicon-remove-circle"></span>
</div>
<ul class="list-group resultUl" data-ref="${ref}"></ul>
</div>`
)
});
},
}
})($);
I tried to add this code to above but it doesn't work.
$('#result').on('click', 'li', function() {
var name = $(this).data('name' );
var code = $(this).data('code' );
var location = $(this).data('location' );
var click_text = $(this).text().split('|');
$('#search').val($.trim(click_text[0]));
$("#result").html('');
$('#result').after('<input type="hidden" name="name" value="'+name+'">');
$('#result').after('<input type="hidden" name="code" value="'+code+'">');
$('#result').after('<input type="hidden" name="location" value="'+location+'">');
});
Mainly you need an event handler for the onClick for the li items.
It sets the name as value in the visible fields and creates hidden inputs in the form where you may have as much variables as you like but serialized in any way
Here is your working example
$(document).ready(function() {
Main.init();
});
var Main = (function($) {
return {
vars: {
},
init: function() {
Main.build();
Main.events();
},
events: function() {
$(document).on('keyup', '.search', function() {
const ref = $(this).attr('data-ref');
const {
vars
} = Main;
$(`.resultUl[data-ref="${ref}"]`).html('');
const searchField = $(this).val();
const expression = new RegExp(searchField, "i");
$.each(vars.JSONdata, (key, value) => {
const {
name,
location,
code,
image
} = value;
if (name.search(expression) != -1 || location.search(expression) != -1) {
$(`.resultUl[data-ref="${ref}"]`).append(
`<li
class="list-group-item link-class list-item"
data-name="${name}"
data-code="${code}"
data-location="${location}"
>
<img src="${image}" height="40" width="40" class="img-thumbnail" />
${name}
<span class="text-muted">${location}</span>
</li>
`
);
}
});
}),
$(document).on('click', '.list-item', function() {
const ul = $(this).closest('ul');
const ref = $(ul).attr('data-ref');
const name = $(this).attr('data-name');
const location = $(this).attr('data-location');
const code = $(this).attr('data-code');
const hiddenInput = $(`.hiddenField[data-ref=${ref}]`);
//console.log(hiddenInput.length);
$(`.search[data-ref=${ref}]`).val(name);
if (hiddenInput.length) {
$(hiddenInput).val(`${name}_${location}_${code}`);
} else {
$('#submitForm').append(
`<input
type="hidden"
class="hiddenField"
data-ref="${ref}"
name="search_${ref}"
value="${name},${location},${code}}"
/>
`
)
}
$(ul).html('');
})
},
build: async function() {
JSONdata = await this.getJson(); //JSONdata is a global variable which you can access from everywhere
this.vars = {
JSONdata
};
this.generateFields(20);
},
getJson: () => new Promise((resolve, reject) => {
// Change the path below with the path for your script
$.getJSON('https://api.myjson.com/bins/lpizs', (data) => {
resolve(data);
}).fail(function() {
reject([]);
})
}),
generateFields: (fieldNumber) => {
Array(fieldNumber).fill().map((v, i) => {
const ref = i + 1;
$('#container').append(
`<div class="fieldContainer">
<div class="btn-group">
<input type="text" class="search" data-ref="${ref}" placeholder="製品 その1" class="form-control" size="3000" onkeypress="return event.keyCode!=13" />
<span class="searchclear glyphicon glyphicon-remove-circle"></span>
</div>
<ul class="list-group resultUl" data-ref="${ref}"></ul>
</div>`
)
});
},
}
})($);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>
<head>
<title>JQuery</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" />
</head>
<body>
<br /><br />
<div class="container" style="width:900px;">
<h2 align="center"></h2>
<h3 align="center"></h3>
<br /><br />
<div align="center">
<div id="container">
</div>
<br />
<form action="recive.php" method="post" id="submitForm">
<input type="submit" id="submit" />
</form>
</div>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script type="text/javascript" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</body>
</html>
I have a service, say this one that returns
{"001":"Communication","002":"Developement","003":"Environment","004":"Equipment"}
I need to put this all in checkboxes, users enable-disable them and finally I recuperate the checked values as CSV keys.
Say user checked the "Development" and "Equipment", so I need to obtain in the "002,004" value.
Here is my codepen with some values already checked (002-Developement and 003-Environment):
angular.module('tagsApp', [])
.controller('tagsController', ['$scope', '$http', function ($scope, $http) {
// an initial value is present in the #Tags hidden element
$scope.tags = $('#Tags').val();
var tags = $scope.tags.split(",");
// I need an obj['key']='key' array
$scope.myTagsArray = {};
tags.forEach(function (tag) { $scope.myTagsArray[tag] = tag; });
// get all possible values
$http.get("http://www.mocky.io/v2/597866a7130000d704c0fed3")
.then(function (response) {
$scope.allTags = response.data;
});
$scope.change = function (myTagsArray) {
console.log("myTagsArray: '" + Object.values($scope.myTagsArray).join(",") + "' !");
};
}]);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="tagsApp">
<label>Tags</label>
<div ng-controller="tagsController">
<input type="hidden" id="Tags" value="002,003"/>
<div ng-cloak ng-repeat="(key, value) in allTags">
<label for="tag_{{key}}">
<input type="checkbox"
id="tag_{{key}}"
ng-model="tagsArray['{{key}}']"
ng-true-value="'{{key}}'"
ng-false-value=""
ng-change="change(tagsArray)" />
{{value}}
</label>
</div>
</div>
</div>
However all that code does not really work. Where is the problem?
You can try the below code if you want the corresponding keys to be saved on checking
angular.module("tagsApp", []).controller("tagsController", [
"$scope",
"$http",
function($scope, $http) {
// get all possible values
$scope.allTags = {
"001": "Communication",
"002": "Developement",
"003": "Environment",
"004": "Equipment"
};
$scope.hidval="002,003";
$scope.checked = [];
$scope.tags = [];
$scope.keys = [];
$scope.tags = $scope.hidval.split(",");
$scope.tags.forEach(function(tag) {
$scope.checked[tag] = true;
$scope.keys.push(tag);
});
$scope.change = function(mykey) {
var ind = $scope.keys.indexOf(mykey);
if ($scope.checked[mykey]) {
$scope.checked[mykey] = false;
$scope.keys.splice(ind, 1);
} else {
$scope.checked[mykey] = true;
$scope.keys.push(mykey);
}
var result=$scope.keys.join();
console.log(result);
$scope.hidval=result;
};
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="tagsApp">
<label>Tags</label>
<div ng-controller="tagsController">
<input type="hidden" id="Tags" ng-model="hidval"/>{{hidval}}
<div ng-cloak ng-repeat="(key, value) in allTags">
<label for="tag_{{key}}">
<input type="checkbox"
id="tag_{{key}}"
ng-checked="checked[key]"
ng-click="change(key)"/>
{{value}}
</label>
</div>
</div>
</div>
Based on the Vivz answer (thanks a lot for the effort), here is the working solution
angular.module("tagsApp", []).controller("tagsController", [
"$scope",
function($scope) {
// get all possible values
$scope.allTags = {
"001": "Communication",
"002": "Developement",
"003": "Environment",
"004": "Equipment"
};
$scope.selectedTags = $("#Tags").val().split(",");
$scope.tagsArray = {};
// init all with "false"
Object.keys($scope.allTags).forEach(function(tag) { $scope.tagsArray[tag] = ""; });
// check pre-selected from hidden #Tags
$scope.selectedTags.forEach(function(tag) { $scope.tagsArray[tag] = tag; });
$scope.change = function(mykey) {
var result = Object.values($scope.tagsArray)
.filter(function(o){return o;})
.join(); // remove the empty values in array
$("#Tags").val(result); // update the hidden #Tags
console.log(result);
};
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="tagsApp">
<label>Tags</label>
<div ng-controller="tagsController">
<input type="hidden" id="Tags" value="002,003"/>
<div ng-cloak ng-repeat="(key, value) in allTags">
<label for="tag_{{key}}">
<input type="checkbox"
id="tag_{{key}}"
ng-model="tagsArray[key]"
ng-true-value="{{key}}"
ng-false-value=""
ng-change="change(key)" />
{{value}}
</label>
</div>
</div>
</div>
Im trying to create a simple login verification, however the validation function seizes to function when the validation comparison begins, and the console sais that the variable "userName is not defined" although it clearly is.
Can enyone tell me what am i defining wrong?
the angular controller code:
var app = angular.module("LoginApp", []);
app.controller("LoginController", function ($http) {
this.userName = "";
this.password = "";
this.userNameValid = true;
this.passwordValid = true;
/*submit the form*/
this.submit = function () {
alert("submit");
this.validate();
};
/* make sure user name and password has been inserted*/
this.validate = function () {
alert("validate");
var result = true;
this.userNameValid = true;
this.passwordValid = true;
if (this.userName == "") {
alert("username="+userName);
this.userNameValid = false;
result = false;
}
if (this.password == "") {
this.passwordValid = false;
result = false;
}
alert("validuserNameValid==" + userNameValid + " passwordValid==" + passwordValid);
return result;
};
});
the HTML form:
<body ng-app="LoginApp" ng-controller="LoginController as LoginController">
<form role="form" novalidate name="loginForm" ng-submit="LoginController.submit()">
<div id="loginDetails">
<div class="form-group">
<label for="user"> User Name:</label>
<input type="text" id="user" class="form-control" ng-model="LoginController.userName" required />
<span ng-show="LoginController.userNameValid==false" class="alert-danger">field is requiered</span>
</div>
<div class="form-group">
<label for="password" >Password:</label>
<input type="password" id="password" class="form-control" ng-model="LoginController.password" required />
<span ng-show="LoginController.passwordValid==false" class="alert-danger">field is requiered</span>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">Submit</button>
{{"entered information:" +"\n"+LoginController.userName+" "+ LoginController.password}}
</div>
</div>
</form>
</body>
the log:
Error: userName is not defined
this.validate#http://localhost:39191/login.js:23:13
this.submit#http://localhost:39191/login.js:11:9
anonymous/fn#https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js line 231 > Function:2:292
b#https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js:126:19
Kc[b]</<.compile/</</e#https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js:274:195
uf/this.$get</m.prototype.$eval#https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js:145:103
uf/this.$get</m.prototype.$apply#https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js:145:335
Kc[b]</<.compile/</<#https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js:274:245
Rf#https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js:37:31
Qf/d#https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js:36:486
Always use this judiciously. I would recommend you to store the reference of this in variable then use it wherever required.
var app = angular.module("LoginApp", []);
app.controller("LoginController", function ($http) {
//Store the reference of this in a variable
var lc = this;
//Use the stored refrence
lc.userName = "";
/* make sure user name and password has been inserted*/
lc.validate = function () {
if (lc.userName == "") {
alert("username="+userName);
lc.userNameValid = false;
result = false;
}
};
});
inside your alert boxes you have not mentioned this.userName try removing the alert boxes or change them.
The crux of this problem is that assigning a variable to an html element is not working within a constructor function.
There must be a way around this right?
The most effective way I have found is to create a method within the constructor function that returns the element.
The problematic variable is "box".
I commented out the section at the start where I tried to make box a global variable, but the constructor couldn't find the box variable. That is the weirdest part to me.
Below is my sample code:
window.onload = function()
{
document.getElementById("sub_button").onclick = adder;
document.getElementById("scrap_it").onclick = remover;
}
//var box = document.getElementById("contact_list");
//refers to the select tag containing contact names as options
var Contacts = function()
{
this.box = function (){ return document.getElementById("contact_list");}
this.list = [];
this.contact_info = document.getElementById("contact_info");
this.find = function(personName){
var found = "missing";
for(var i = 0; i < this.list.length; i++)
{
if(this.list[i].personName == personName)
{
found = i;
}
}
return found;
}
this.addPerson = function(personName, phone)
{
if (this.find(personName) == "missing")
{
personName = personName;
contact =
{
personName: personName,
phone: phone
}
this.list.push(contact);
this.update();
}
else
{
alert("Sorry, this contact name is already in use. Please choose another.");
}
}
this.update = function()
{
this.box().innerHTML = "";
for (var i = 0; i <this.list.length; i++)
{
option_element = document.createElement("OPTION");
option_node = document.createTextNode(this.list[i].personName);
option_element.appendChild(option_node);
this.box().appendChild(option_element);
}
}
this.remove = function(name_to_delete)
{
var index_to_remove = name_to_delete;
this.list.splice(index_to_remove, 1);
this.update();
}
this.postInfo = function(contact_to_display)
{
var index_to_display = contact_to_display;
alert(this.list[index_to_display].personName);
alert(this.list[index_to_display].phone);
}
}
var myList = new Contacts();
function adder()
{
myList.addPerson(document.getElementById("contact_name").value, document.getElementById("contact_phone").value);
}
function remover()
{
myList.remove(myList.box().selectedIndex);
}
function showInfo()
{
myList.postInfo(myList.box().selectedIndex);
}
And the HTML:
<html>
<head>
<title>Address Book</title>
<script type="text/javascript" src="beta3.js"></script>
</head>
<body>
<form id="contact_form">
<label for="contact_name">Name: </label>
<input type="text" id="contact_name" /><br />
<label for="contact_phone">Phone: </label>
<input type="text" id="contact_phone" /><br />
<input type="button" name="submit" value="submit" id="sub_button" />
</form>
<br />
<div>
Delete
</div>
<br />
<div>
<select name="contact_list" id="contact_list" size="10" multiple="multiple" style="width: 450px">
</select>
</div>
<div>
<textarea id="contact_info">
</textarea>
</div>
</body>
</html>
try something like this
var box;
window.onload = function()
{
document.getElementById("sub_button").onclick = adder;
document.getElementById("scrap_it").onclick = remover;
//refers to the select tag containing contact names as options
box = document.getElementById("contact_list");
}
Your code is not working because your script is executed before our element is render in dom so your box variable get nothing.