Knockout set observable array in array - javascript

I have a small question about knockout.
I have made a viewmodel
that looks like this (there are more subitems then Actions)
{
"PlatformSettings": [
{
"Actions": [
{
"Selected": false,
"Text": "None",
"Value": "None"
},
{
"Selected": true,
"Text": "Validation1",
"Value": "Validation1"
},
{
"Selected": true,
"Text": "Validation2",
"Value": "Validation2"
},
{
"Selected": true,
"Text": "Validation3",
"Value": "Validation3"
}
],
"Platform": {
"Id": "89",
"Description": "ONTWIKKELB"
}
},{
"Actions": [
{
"Selected": false,
"Text": "None",
"Value": "None"
},
{
"Selected": true,
"Text": "Validation1",
"Value": "Validation1"
},
{
"Selected": true,
"Text": "Validation2",
"Value": "Validation2"
},
{
"Selected": true,
"Text": "Validation3",
"Value": "Validation3"
}
],
"Platform": {
"Id": "89",
"Description": "ONTWIKKELB"
}
}
It works fine, but when i edit the checkboxes in my view and map them
self.Save = function(validate) {
var unmapped = ko.mapping.toJSON(self);
******
return false;
};
unmapped doesn't show the changes. And all the select values still show as on page load. I tried to make observable arrays, but the past 2 hours, but i can't figure it out.
Many thanks

Making the array observable will notify subscribers on add\remove. Making the "selected" property of each element observable will notify subscribers when it changes and allow 2 way binding.
So basically, make the selected property of each array element an observable too.

Related

Strapi: trouble populating multi-valued attribute for nested relation

I have a collection called dish-category which contains many dishes, and a dish collection that contains many dish-options (another collection).
the list of dishes from each dish-category is available in the API but the nested collection of dish options from each dish is not available on strapi.
the following are the settings for my models:
dish-category.settings.json:
{
"kind": "collectionType",
"collectionName": "dish_categories",
"info": {
"name": "DishCategory",
"description": ""
},
"options": {
"increments": true,
"timestamps": true,
"draftAndPublish": true
},
"pluginOptions": {},
"attributes": {
"Name": {
"type": "string"
},
"Description": {
"type": "text"
},
"dishes": {
"collection": "dish",
"via": "dish_category"
}
}
}
dish.settings.json:
{
"kind": "collectionType",
"collectionName": "dishes",
"info": {
"name": "Dish",
"description": ""
},
"options": {
"increments": true,
"timestamps": true,
"draftAndPublish": true
},
"pluginOptions": {},
"attributes": {
"Name": {
"type": "string"
},
"Description": {
"type": "text"
},
"Total": {
"type": "decimal",
"min": 0,
"required": false,
"default": 0
},
"dish_categories": {
"collection": "dish-category"
},
"dish_options": {
"collection": "dish-option",
"via": "dish"
},
"dish_category": {
"via": "dishes",
"model": "dish-category"
}
}
}
dish-option.settings.json:
{
"kind": "collectionType",
"collectionName": "dish_options",
"info": {
"name": "DishOption",
"description": ""
},
"options": {
"increments": true,
"timestamps": true,
"draftAndPublish": true
},
"pluginOptions": {},
"attributes": {
"Name": {
"type": "string"
},
"Price": {
"type": "decimal",
"min": 0,
"default": 0
},
"dish": {
"via": "dish_options",
"model": "dish"
}
}
}
on the dish-category/controllers/dish-category.js file I tried populating the attribute:
'use strict';
/**
* Read the documentation (https://strapi.io/documentation/developer-docs/latest/development/backend-customization.html#core-controllers)
* to customize this controller
*/
module.exports = {
async find(params, populate){
return strapi.query('dish-category').find(params, ["dishes","dish.dish_options"]);
}
};
I am having trouble displaying nested relations with multiple values, I have tried looking up solutions online, I came across this thread https://forum.strapi.io/t/simple-nested-array-issue/1045/4 but the solution doesn't work for me and it seems like the link to the example is no longer available.

How to check any every array object property empty or not?

The purpose of function is to get false when all answers are empty. Currently, some how getting **false when only one single answers empty and rest have data inside.
what is the best way to check all answers are empty or not. It doesn't matter some has data and some doesn't. I just wanna see all empty or not.
const questions = [{
"answers": [{
"value": "Browns",
"selected": false,
},
{
"value": "Oranges",
"selected": false,
},
{
"value": "Purples",
"selected": false,
}
],
"info": "",
"type": "DESELECT",
"lastUpdated": "2021-11-01T22:50:28.359"
},
{
"answers": [],
"info": "",
"type": "DESELECT",
"lastUpdated": "2021-11-01T22:50:35.392"
},
{
"answers": [{
"value": "AnimalPrints",
"selected": false,
},
{
"value": "BigLogos",
"selected": true,
},
{
"value": "Floral",
"selected": false,
}
],
"info": "",
"type": "DESELECT",
"lastUpdated": "2021-11-01T22:50:43.883"
}
];
console.clear();
console.log("------------ES6------------");
const es6Result = questions.every((item) => !_.isEmpty(item.answers));
console.log(es6Result);
const lodashResult = _.every(questions, !_.isEmpty('answers'));
console.log("------------Lodash------------");
console.log(lodashResult);
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.21/lodash.min.js"></script>
You could use .some(), you will get true if at least 1 answers is not empty, and you will get false if all answers are empty
const es6Result = questions.some((item) => item.answers.length);
I think the logic you describe requires:
const lodashResult = !_.every(questions, _.isEmpty('answers'));
or
const es6Result = !questions.every((item) => _.isEmpty(item.answers));
const questions = [{
"answers": [{
"value": "Browns",
"selected": false,
},
{
"value": "Oranges",
"selected": false,
},
{
"value": "Purples",
"selected": false,
}
],
"info": "",
"type": "DESELECT",
"lastUpdated": "2021-11-01T22:50:28.359"
},
{
"answers": [],
"info": "",
"type": "DESELECT",
"lastUpdated": "2021-11-01T22:50:35.392"
},
{
"answers": [{
"value": "AnimalPrints",
"selected": false,
},
{
"value": "BigLogos",
"selected": true,
},
{
"value": "Floral",
"selected": false,
}
],
"info": "",
"type": "DESELECT",
"lastUpdated": "2021-11-01T22:50:43.883"
}
];
console.clear();
console.log("------------ES6------------");
const es6Result = questions.map((item) => _.isEmpty(item.answers)).indexOf(true) > -1;
console.log(es6Result);
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.21/lodash.min.js"></script>
There's not really a need for lodash here. You should be able to accomplish what you want by using Array.prototype.every
questions.every((item) => item.answers.length > 0)
This will always return true, as long as all 'answers' array have one or more items inside, else false.
As Georgy said, you can use Array.prototype.some when you want to check for at least one of the items.

How to structure my json value that got pushed to array in angular.js

This is my punker
I can get the selected values pushed to array by ngcheck and ngchange, but I want to push the {{get_ing_value.productName}} to array when I click any of the checkbox and radio button.
This is what I have:
[
{
"selected": {
"_id": "584aa4e218c5b62c02b6fe6a",
"productId": "584aa4e118c5b62c02b6fe67",
"ingredientTypeId": "5822f17b24baa627770af5ed",
"ingredientName": "small",
"slug": "small",
"isActive": true,
"ingredientPrice": -75
}
},
{
"selected": {
"_id": "584aa4e718c5b62c02b6fe6e",
"productId": "584aa4e118c5b62c02b6fe67",
"ingredientTypeId": "5822f18324baa627770af5ee",
"ingredientName": "extra cheese",
"slug": "extra-cheese",
"isActive": true,
"ingredientPrice": 20
}
},
{
"selected": "{\"_id\":\"584aa4e918c5b62c02b6fe70\",\"productId\":\"584aa4e118c5b62c02b6fe67\",\"ingredientTypeId\":\"5822f19724baa627770af5ef\",\"ingredientName\":\"hot chilly\",\"slug\":\"hot-chilly\",\"isActive\":true,\"ingredientPrice\":20}"
},
{
"selected": "{\"_id\":\"584aa4ea18c5b62c02b6fe71\",\"productId\":\"584aa4e118c5b62c02b6fe67\",\"ingredientTypeId\":\"5822f1a024baa627770af5f0\",\"ingredientName\":\"chicken\",\"slug\":\"chicken\",\"isActive\":true,\"ingredientPrice\":50}"
}
]
This is what I want to get
[
{
"main_product_name": "PIZAA"
},
{
"selected": {
"_id": "584aa4e218c5b62c02b6fe6a",
"productId": "584aa4e118c5b62c02b6fe67",
"ingredientTypeId": "5822f17b24baa627770af5ed",
"ingredientName": "small",
"slug": "small",
"isActive": true,
"ingredientPrice": -75
}
},
{
"selected": {
"_id": "584aa4e718c5b62c02b6fe6e",
"productId": "584aa4e118c5b62c02b6fe67",
"ingredientTypeId": "5822f18324baa627770af5ee",
"ingredientName": "extra cheese",
"slug": "extra-cheese",
"isActive": true,
"ingredientPrice": 20
}
},
{
"selected": "{\"_id\":\"584aa4e918c5b62c02b6fe70\",\"productId\":\"584aa4e118c5b62c02b6fe67\",\"ingredientTypeId\":\"5822f19724baa627770af5ef\",\"ingredientName\":\"hot chilly\",\"slug\":\"hot-chilly\",\"isActive\":true,\"ingredientPrice\":20}"
},
{
"selected": "{\"_id\":\"584aa4ea18c5b62c02b6fe71\",\"productId\":\"584aa4e118c5b62c02b6fe67\",\"ingredientTypeId\":\"5822f1a024baa627770af5f0\",\"ingredientName\":\"chicken\",\"slug\":\"chicken\",\"isActive\":true,\"ingredientPrice\":50}"
}
]
You can try this code, may be it helps you. It will set PIZZA as main_product_name in first index of your array when you select any radio or checkbox, it will also check if main_product_name is already added.
var App = angular.module('App', []);
App.controller('TodoCtrl', function($scope, $http) {
$scope.get_product_ingredients;
$http.get('https://api.myjson.com/bins/1gh1pl').then(function(res) {
$scope.get_product_ingredients = res.data;
});
$scope.selected_ingrediants = [];
$scope.tempCheck = {};
$scope.formatted = [];
$scope.get = function() {
if(!$scope.formatted[0]){
$scope.formatted[0] = {
main_product_name: $scope.get_product_ingredients[0].productName
}
}
};
$scope.updateIngredient = function(type, model, index){
if(!$scope.formatted[0]){
$scope.formatted[0] = {
main_product_name: $scope.get_product_ingredients[0].productName
}
}
$scope.formatted[index+1] = {
//ingredientTypeName: type,
selected: model
}
}
});

Loopback and MongoDB

I've been trying to create a collection that contains an array of objects in loopback.
I want a store data formatted like this:
{
id: "16356135616aaasad", //autogenerated by mongo
"name" : "a name",
"valores": [
{"valor": 567, "fecha": "2016-08-18T00:00:00.000Z"},
{"valor": 569, "fecha": "2016-08-19T00:00:00.000Z"},
...
]
}
I have the following configuration in loopback:
indicador.json
{
"name": "Indicador",
"plural": "indicadores",
"base": "PersistedModel",
"idInjection": true,
"options": {
"validateUpsert": true,
"autoId": true
},
"properties": {
"nombre": {
"type": "string",
"required": true
}
},
"relations": {
"historico": {
"type": "embedsMany",
"model": "Valor"
}
}
}
this is a base collection associated to another model (not persistent)
valor.json
{
"name": "Valor",
"plural": "valores",
"base": "Model",
"properties": {
"valor": {
"type": "number",
"required": true
},
"fecha": {
"type": "date",
"required": true
}
}
}
The problem it's when i try to send a post to the endpoint. If i send this data
{
"nombre": "UF",
"valores": [
{
"valor": 0,
"fecha": "2016-08-18"
}
]
}
The API responses this:
{
"error": {
"name": "ValidationError",
"status": 422,
"message": "The `Indicador` instance is not valid. Details: `valores` contains invalid item at index `0`: `id` is blank (value: [ { valor: 0, fecha: 2016...} ]).",
"statusCode": 422,
"details": {
"context": "Indicador",
"codes": {
"valores": [
"invalid"
]
},
"messages": {
"valores": [
"contains invalid item at index `0`: `id` is blank"
]
}
},
"stack": "ValidationError: The `Indicador` instance is not valid. Details: `valores` contains invalid item at index `0`: `id` is blank (value: [ { valor: 0, fecha: 2016...} ]).\n at /home/dev/app/node_modules/loopback-datasource-juggler/lib/dao.js:322:12\n at ModelConstructor.<anonymous> (/home/dev/app/node_modules/loopback-datasource-juggler/lib/validations.js:492:11)\n at ModelConstructor.next (/home/dev/app/node_modules/loopback-datasource-juggler/lib/hooks.js:81:12)\n at ModelConstructor.<anonymous> (/home/dev/app/node_modules/loopback-datasource-juggler/lib/validations.js:489:23)\n at ModelConstructor.trigger (/home/dev/app/node_modules/loopback-datasource-juggler/lib/hooks.js:71:12)\n at ModelConstructor.Validatable.isValid (/home/dev/app/node_modules/loopback-datasource-juggler/lib/validations.js:455:8)\n at /home/dev/app/node_modules/loopback-datasource-juggler/lib/dao.js:318:9\n at doNotify (/home/dev/app/node_modules/loopback-datasource-juggler/lib/observer.js:98:49)\n at doNotify (/home/dev/app/node_modules/loopback-datasource-juggler/lib/observer.js:98:49)\n at doNotify (/home/dev/app/node_modules/loopback-datasource-juggler/lib/observer.js:98:49)"
}
}
¿Why i get this error?
The id inside the objects of the array that I need isn't necessary for me. I don't understand why happen this.
You need to specify that embedded model doe not need id
"relations": {
"historico": {
"type": "embedsMany",
"model": "Valor",
"options": {
"forceId": false,
"validate": true,
"persistent": false
}
}
}
You need to add "defaultFn":"uuid" to the id property in the json of the model that is going to be embeded in order to have the id generated. In your case it will look like the following:
{
"name": "Valor",
"plural": "valores",
"base": "Model",
"properties": {
"id":{
"type": "string",
"defaultFn":"uuid",
"id":true
},
"valor": {
"type": "number",
"required": true
},
"fecha": {
"type": "date",
"required": true
}
}
}

Javascript loop through JSON object

What I am trying to do exceeds my knowledge. Thank you all for your time and help, it is a great pleasure to have the support of such a large community of great developers.
The problem
I need to loop over an object (JSON response) to determine which data is true and then edit the html with the results.
json object is:
var data = {
"total": 4,
"limit": 50,
"questions": [{
"date_created": "2015-06-29T18:24:25.000-04:00",
"item_id": "MLA567045929",
"seller_id": 186626557,
"status": "UNANSWERED",
"text": "Pregunta de Testeo, user 2.",
"id": 3612747353,
"deleted_from_listing": false,
"hold": false,
"answer": null,
"from": {
"id": 186625262,
"answered_questions": 0
}
}, {
"date_created": "2015-06-29T18:30:16.000-04:00",
"item_id": "MLA567045929",
"seller_id": 186626557,
"status": "UNANSWERED",
"text": "Lorem ipsum dolor sit amet",
"id": 3612938882,
"deleted_from_listing": false,
"hold": false,
"answer": null,
"from": {
"id": 186625262,
"answered_questions": 0
}
}, {
"date_created": "2015-06-29T18:30:35.000-04:00",
"item_id": "MLA567045929",
"seller_id": 186626557,
"status": "UNANSWERED",
"text": "an est odio timeam quaerendum",
"id": 3612752695,
"deleted_from_listing": false,
"hold": false,
"answer": null,
"from": {
"id": 186625262,
"answered_questions": 0
}
}, {
"date_created": "2015-06-29T18:31:32.000-04:00",
"item_id": "MLA567045929",
"seller_id": 186626557,
"status": "ANSWERED",
"text": "Responder esta pregunta",
"id": 3612753455,
"deleted_from_listing": false,
"hold": false,
"answer": {
"text": "Pregunta respondida",
"status": "ACTIVE",
"date_created": "2015-06-29T18:31:58.000-04:00"
},
"from": {
"id": 186625262,
"answered_questions": 1
}
}],
"filters": {
"limit": 50,
"offset": 0,
"is_admin": false,
"sorts": [],
"caller": 186626557,
"seller": "186626557"
},
"available_filters": [{
"id": "item",
"name": "Item",
"type": "text"
}, {
"id": "from",
"name": "From user id",
"type": "number"
}, {
"id": "totalDivisions",
"name": "total divisions",
"type": "number"
}, {
"id": "division",
"name": "Division",
"type": "number"
}, {
"id": "status",
"name": "Status",
"type": "text",
"values": ["BANNED", "CLOSED_UNANSWERED", "DELETED", "DISABLED", "UNDER_REVIEW"]
}],
"available_sorts": ["item_id", "from_id", "date_created", "seller_id"]
};
The result I'm looking for is:
Of the data object, I need to extract questions with the status unanswered and the id field associated with these unanswered questions.
"questions1":[{ "status" : "UNANSWERED",
"id" : 3612747353}],
"questions2":[{ "status" : "UNANSWERED",
"id" : 3612938882}],
...
Based on what I've searched, I've tried with loops, for in, and each without success.
Any suggestions or ideas on how I could achieve the desired result? I need to apply this example to several objects.
Try some handy list processing functions to simplify it conceptually. The filter and map functions will help. The function I provided to filter tells it to only let through items that meet the condition of having an unanswered status. The function I provided to map turned all the objects that came out of filter into just their ids.
data["questions"].filter(function(obj) {
return obj["status"] === "UNANSWERED";
}).map(function(obj) {
return obj["id"];
});
var results = [];
for (var question in data.questions) {
if (data.questions[question].status === "UNANSWERED") {
results.push({
"status" : data.questions[question].status,
"id" : data.questions[question].id
});
}
}
// Now results contains an array of unanswered questions,
// with just their status & id.
You can just loop through the questions and save the ids you want to an array:
var questions = data.questions;
var unanswered = [];
for(var i = 0, len = questions.length; i < len; i++) {
if(questions[i].status === 'UNANSWERED') {
unanswered.push(questions[i].id);
}
}
unanswered will be an array of unanswered question ids. You don't need to save the status; you know they are all 'UNANSWERED'.

Categories