How to use "multiple arrays" in "each" cycle in javascript - javascript

i want the product pages marked as PageType = 'item' (inside only one category) to display different HTML code according to language mutation of a webpage. What i've achieved so far is that on every mutation page is the same content X times (x = object items such as "eng": "categoryname" )
var html = `
<div class="">
<a class="" href="#" target="_blank">
<img src="different images with site language mutation" alt="banner">
</a>
</div>
`;
var langcode = $('html').attr('lang');
var maincat = [];
$(".breadcrumbclass").each(function() {
var vat = $(this).text();
maincat.push(vat);
});
var mycategory = maincat[1];
$.each(langmutations, function(key, val) {
if (((PageType == 'item') || (PageType === 'category')) && (mycategory === langmutations[langcode])) {
$('.classForPastingMyHtml').after(html);
}
});
//This is what i have in JS
var langmutations0 = {
eng: 'categoryname',
de: 'kategoriename',
ru: 'categorija'
};
//or
var langmutations1 = [
["eng", "categoryname"],
["de", "kategoriename"],
["ru", "categorija"]
];
//I believe this is PHP style
var langmutations2 = ['eng' => 'categoryname', 'de' => 'kategoriename', 'ru' => 'categorija'];
//This could be multiple array in PHP style ? I want to have this in JS
var multiple = [eng => [“cat” => “categoryname”, “banner” => “link”], de => [“cat” => “kategoriename”, “banner” => “link”], ru => [“cat” => “categorija”, “banner” => “link”]];
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
I think that i should use something like multiple array, but don't know if that exists in JS or how to structure it. Or maybe javascript object that would respond to that PHP style.

Here is some simple code to get you started:
var multiple = {
eng : {"cat" : "categoryname", "banner" : "link"},
de : {"cat" : "Kategoriename", "banner" : "link"},
ru : {"cat" : "categorija", "banner" : "link"}
};
var language = 'de';
var translations = multiple[language];
var cat = translations.cat;
console.log(cat);
//Show all translations
$.each(multiple, function(language,translations){
var cat = translations.cat;
console.log(cat);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
It uses objects inside objects with language as keys.

Related

How is it possible that piece of code that was working is now ignored?

I have coded a ajax based "JS TABS" containing .JSON file like 10 months ago, now wanted to reuse it, and can't find out why it's not working. I haven't touched it since and don't know where is the bug.
When i click the button to render products nothing prints out - except console telling me: items is undefined = so i moved it inside function changeCategoryItems(categoryId) { } well no errors but nothing renders...can someone help me ?
Here is a codepen reference of what i mean: https://codepen.io/Contemplator191/pen/WNwgypY
And this is JSON : https://api.jsonbin.io/b/5f634e0c302a837e95680846
If codepen is not suitable/allowed here is whole JS for that
let items = [];
const buttons = document.querySelectorAll('button');
const wrapper = document.querySelector('section.products');
buttons.forEach(function (button) {
button.addEventListener('click',event => {
changeCategoryItems(event.target.dataset.category);
});
});
function changeCategoryItems(categoryId) {
let items = [];
const buttons = document.querySelectorAll('button');
const wrapper = document.querySelector('section.products');
const viewItems = (categoryId == 0 ) ? items : items.filter(item => item.category == categoryId);
wrapper.innerHTML = "";
viewItems.forEach(item => {
const div = document.createElement('div');
div.setAttribute("class", "product");
div.innerHTML = createItem(item);
wrapper.appendChild(div);
});
};
function createItem(item) {
return `
<div class="product__img">
<img src="${item.img}" class="">
</div>
<div class="product__name _tc">
<h4 class="">${item.heading}</h4>
</div>
<div class="text-desc product__desc">
<p class="">${item.description}</p>
</div>
<div class="product__bottom-content">
<span class="product__info">${item.info}</span>
${item.btn}
</div>
`
}
fetch('https://api.jsonbin.io/b/5f634e0c302a837e95680846')
.then(function (res) { return res.json() })
.then(function (data) {
items = data.items;
changeCategoryItems(1);
});`
In your fetch you're trying to assign data.items to the items variable but the api doesn't return data with an items node so items is undefined. It's possible the api changed their return format since the last time you used it which would explain why it worked previously.
this seems to fix it
.then(function (data) {
items = data;
changeCategoryItems(1);
});
Your issue is in this line:
items = data.items;
Now, the returned value is an array, hence you can use it as it is.
The updated codepen

How to put content in a multi dimensional array in jquery.javascript

I have a function which is triggered on by the click of an update button. When the button is clicked all the elements in a list from a particular div are captured. Each list has about 3 to 4 data attributes. I want create an array in jquery or javascript where the created array is grouped by certain data attributes. Below is the function am using
<div>
<ul id="listDiv" >
<li style="" id="id1" data-type="edit" data-seq="1" data-name="name1">Name1</li>
<li style="" id="id2" data-type="edit" data-seq="2" data-name="name2">Name2</li>
<li style="" id="id3" data-type="create" data-seq="3" data-name="name3">Name3</li>
</ul>
</div>
<a class='upBtn' > Update </a>
$('.upBtn').on('click', function(){
var data = [];
$('#lisDiv li').each(function() {
var id = $(this).attr('id');
var type = $(this).attr('data-type');
data[type]= [];
data[type][id] = [];
data[type][id]['type'] = $(this).attr('data-type');
data[type][id]['seq'] = $(this).attr('data-sequence');
data[type][id]['name'] = $(this).attr('data-name');
});
console.log(data);
})
I tried using push as much as possible. But I am not getting the result I intended. I want the result to be like the format, below:
[edit] => [id1] => ('type') => 'edit',
('seq') => 2,
('name') => 'name1'
[id2] => ('type') => 'edit',
('seq') => 1,
('name') => 'name2'
[create] => [id3] => ('type') => 'edit',
('seq') => 3,
('name') => 'name3'
[id4] => ('type') => 'edit',
('seq') => 4,
('name') => 'name4
'
But whenever I try the array is not getting pushed. I am not sure how to use push here. Any help is highly appreciated.
You need to take objects instead of arrays.
By taking array, you get still the properties, but you can neither see them with console.log, nor stringify them, because an array is stringified with the numerical (positive 32 bit integer) indices.
var data = {};
// ...
data[type] = data[type] || {};
data[type][id] = {};
In your code, you have the wrong identifier, it should be listDev and you need to use a default value for assigning the type.
$('.upBtn').on('click', function() {
var data = {};
$('#listDiv li').each(function() { // listDiv spelling
var id = $(this).attr('id'),
type = $(this).attr('data-type');
data[type] = data[type] || {}; // prevent overwriting the object
data[type][id] = {
type: $(this).attr('data-type'),
seq: $(this).attr('data-seq'), // seq instead of sequence
name: $(this).attr('data-name')
};
});
console.log(data);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<ul id="listDiv">
<li style="" id="id1" data-type="edit" data-seq="1" data-name="name1">Name1</li>
<li style="" id="id2" data-type="edit" data-seq="2" data-name="name2">Name2</li>
<li style="" id="id3" data-type="create" data-seq="3" data-name="name3">Name3</li>
</ul>
</div>
<a class='upBtn'>Update</a>

Nested form Collection in symfony 2

I have a Form which includes a collection type field, inside the collection type field there is one more collection type field. I have to add nested form fields in the twig but I am unable to populate the form fields and wasn't able to find a example where it shows, how nested fields can be populated with JQuery.
First form class :
class SurveyType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add(
'questiongroups',
CollectionType::class,
[
'entry_type' => QuestionGroupType::class,
'allow_add' => true,
'allow_delete' => true,
'entry_options' => [
'submitOption' => $options['submitOption']
]
]
);
}
Second form class which have another collection type field :
class QuestionGroupType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add(
'questions',
CollectionType::class,
[
'entry_type' => QuestionType::class,
'allow_add' => true,
'allow_delete' => true,
'entry_options' => [
'submitOption' => $options['submitOption']
],
'prototype_name' => '__que__'
]
);
}
On twig I its like this:
<ul id="questiongroups-field-list" data-prototype-question="{{ form_widget(form.questiongroups.vars.prototype.children['questions'].vars.prototype)|e }}"
data-prototype="{{ form_widget(form.questiongroups.vars.prototype)|e}}"
data-widget-tags="{{'<li></li>'|e}}">
My Jquery for Populating the fields:
$(document).on('click', '.add-another-collection-widget', function(e){
var list = $($(this).attr('data-list'));
var counter = list.data('widget-counter') | list.children().length;
var newWidget = list.attr('data-prototype');
newWidget = newWidget.replace(/__name__/g, counter);
console.log(newWidget);
counter++;
list.data('widget-counter', counter);
var newElem = jQuery(list.attr('data-widget-tags')).html(newWidget);
newElem.appendTo(list);
addTagFormDeleteLink(newElem);
});
function addTagFormDeleteLink($tagFormLi) {
var $addQuestionButton = $('<button class="button" type="button">Add Question</button>');
var $removeFormButton = $('<button class="alert button" type="button">Delete Group</button>');
$tagFormLi.append($addQuestionButton);
$tagFormLi.append($removeFormButton);
$removeFormButton.on('click', function(e) {
// remove the li for the tag form
$tagFormLi.remove();
});
$addQuestionButton.on('click', function(){
var list = $('#questiongroups-field-list');
var counter = list.data('widget-counter') | list.children().length;
var newWidget = list.attr('data-prototype-question');
newWidget = newWidget.replace(/__name__/g, counter);
counter++;
list.data('widget-counter', counter);
$tagFormLi.append(newWidget);
});
}
After carefully going through the prototype variables. This is how I have modified the code of Single form collection into nested form collection:
Prototye Field Changes:
<ul id="questiongroups-field-list" data-prototype-question = "{{ form_widget(form.questiongroups.vars.prototype.children['questions'].vars.prototype)|e }}"
data-prototype="{{ form_widget(form.questiongroups.vars.prototype)|e}}"
data-widget-tags="{{'<li></li>'|e}}" data-tag-list = "{{ '<ul class="question-list"></ul>' |e}}">
Below is the Jquery Code:
$(document).on('click', '.add-questiongroup[data-target]', function(event) {
var collectionHolder = $($(this).attr('data-target'));
if (!collectionHolder.attr('data-counter')) {
collectionHolder.attr('data-counter', collectionHolder.children().length);
}
var prototype = collectionHolder.attr('data-prototype');
var form = prototype.replace(/__name__/g, collectionHolder.attr('data-counter'));
newWidget = $(collectionHolder.attr('data-widget-tags')).html(form);
newWidget.append(collectionHolder.attr('data-tag-list'));
collectionHolder.attr('data-counter', Number(collectionHolder.attr('data-counter')) + 1);
collectionHolder.append(newWidget);
var questionPrototype = collectionHolder.attr('data-prototype-question');
var counter = collectionHolder.attr('data-counter');
newWidget.attr('data-counter', counter);
addTagFormDeleteLink(newWidget);
$('.option-min, .option-max').parent().hide();
event && event.preventDefault();
});
function addTagFormDeleteLink(newWidget) {
$removeFormButton = $('<button type="button" class="alert button">Delete Group</button>');
$addQuestionButton = $('<button type="button" class="button">Add Question</button><br>');
$removeQuestion = $('<button type="button" class="alert button deleteQuebtn">Delete Question</button>');
newWidget.append($addQuestionButton);
newWidget.append($removeFormButton);
$removeFormButton.on('click', function(e) {
newWidget.remove();
});
$addQuestionButton.on('click', function(e){
$holder = $('#questiongroups-field-list');
$question = $holder.attr('data-prototype-question');
$questionHolder = newWidget.find('ul');
var counter = $questionHolder.children().length;
var form = $question.replace(/__name__/g, $holder.attr('data-counter')-1).replace(/__que__/g, counter++);
var newQuestion = $($holder.attr('data-widget-tags')).html(form);
$questionHolder.append(newQuestion);
});
}
forms are a pain in cases like these
I normally resolve, and I propose it for you in this context, in another way:
every piece of html displaying a single item of a collection is loaded via AJAX (what I call "subform")
so, when I need to add an item of a collection in a form, I do:
/**
* #Route("edit/break-evens/_form", name="admin_ride_edit_ride_break_evens_subform", options={"expose"=true}, methods={"GET"})
*/
public function _formAction()
{
$entity = new Ride();
$entity->addBreakEven(new BreakEven());
$form = $this->createForm(
RideType::class,
$entity
);
$form = $form->get('breakEvens')[0];
return $this->render('AdminBundle:Ride:_edit.html.twig', [
'form' => $form->createView(),
]);
}
where:
Ride is 1:n with BreakEven, as to say that breakEvens is a Collection in a RideType form
so, when I want to add an item:
I call the action above
I create a "full" form, adding an item (new BreakEven()) of the interested collection
I create the view only for the first object of the collection
then change the number of the form field with js when loaded
of course if you have collections of collections the thing get more difficult, but the you can consider the concept

Kendo grid Template is not working with html encoded symbol ( ' ), it shows the names with apostrophe like sam's as sam &#39s

I have a angular 2 application. Where I am using kendo grid to to bind the data to display in the table cells. In the template cell all is fine but wherever we have an apostrophe s in the names there it breaks up, it shows like this
The temple for the kendo grid component i am providing below, i am looking for the code to improve the view that shows ' instead of &#39. I am not able to find where I should add the code to existing code to make it work because the dataItem is holding the names and it is coming from template binding. can i add an auxiliary global JavaScript function that can be used to manipulate each data item during display.
two-dimensional-grid.html -
<template kendoGridCellTemplate let-dataItem let-rowIndex="rowIndex" >
<span *ngIf="column !== 'Percentage'">
<span style="color:#3b73af;cursor:pointer">
<span [class.twoDimGrid]="column === header">
<span (click)="rowItemClick(dataItem, column)">
{{dataItem[column]}}
</span>
</span>
</span>
</span>
two-dimensional-grid.ts
ngOnInit() {
this.columns = [];
this.gridTitle = this.twoDimensionalGridInfo.Name;
this.baseJql = this.twoDimensionalGridInfo.jql;
this.type = this.twoDimensionalGridInfo.type;
this.summary = this.twoDimensionalGridInfo.summary;
if (this.summary) {
this.fields = this.summary.split('|');
this.y = this.fields[0];
this.x = this.fields[1];
}
let dataItem = this.gridData[0];
if (dataItem) {
var keys = Object.keys(dataItem);
this.header = keys[0]
}
for (let field in dataItem) {
this.columns.push(field);
}
this.total = this.gridData.reduce((sums, obj) => Object.keys(obj).reduce((s, k) => {
k === this.header || k === 'Percentage' || (s[k] = (s[k] || 0) + +obj[k]);
return s;
}, sums), {});
this.total[this.header] = "Total";
this.total["Percentage"] = "";
}
i foud the answer , in the template binding I used instead of {{dataItem[column] }} .
The html code was enecoded in my database, so for decoding again its another method of solving, but i found this way too it worked for me.

get checkbox array value in angular JS

I've seen a few posts asking the same question but I can't make it work. I'm quite new to angular so I would need help.
I'm trying to insert a new income with tags.
I get thoses tags from a service and display them like this :
<label ng-repeat="tag in tags">
<input type="checkbox" ng-model="tags_chosen" name="tags_chosen[tag]" ng-true-value="<%tag.id%>"/> <%tag.name%>
</label>
When I try to get back the checkbox values in angular, it doesn't work :
this.addIncome = function($scope) {
var data = {
'project_id':$scope.project_id,
'amount':$scope.amount,
'payment_date':$scope.payment_date,
'tags':$scope.tag_chosen,
'description':$scope.description,
'type':$scope.type
};
return $http.post(URL.BASE_API + 'income/store',data).
success(function(response) {
ServicesStatus.return = response;
}).error(function(response) {
console.log('Service error');
});
};
How could I do that ?
Thanks !
try this:
$scope.tag_chosen =[];
$scope.toggleSelection = function ( deviceId, $event ) {
var checkbox = $event.target;
var action=(checkbox.checked ? 'add':'remove');
var idx = $scope.tag_chosen.indexOf( deviceId );
// is currently selected
if (action=='remove' && idx != -1 ) {
$scope.tag_chosen .splice( idx, 1 );
}
// is newly selected
if (action=='add' && idx == -1 ) {
$scope.tag_chosen.push( deviceId );
}
and in html >>
ng-click="toggleSelection(yourcjeckbox value,$event)"

Categories