I have created line chart using Fushionchart in Angular with API data. I have method to add custom color to the chart but it doesn't work. Here I have provide full code to figure the flow. Function pass two parameters and need to set to the label of chart.FYI: *getColorCode() is located in dashboard.service.ts(in below). Here's the full code.
dashboard.component.html
<div *ngIf="multipleConsump" class="chart-card-body p-3">
<app-consumption-summery-chart></app-consumption-summery-chart>
</div>
dashboard.component.ts
getConsumptionData(): void {
this.typeChart.reset();
if (this.trendLogTabIndex == 0 || this.trendLogTabIndex == 1) {
this.tempIntervalid = 2;
} else if (this.trendLogTabIndex == 2) {
this.tempIntervalid = 3;
} else if (this.trendLogTabIndex == 3) {
this.tempIntervalid = 4;
}
this.ltDashboardService
.getCategoryTrends(
this.buildingId,
this.tempIntervalid,
this.intervalTime.from,
this.intervalTime.to,
)
.subscribe(
(res: Object[]) => {
if (res.length) {
const labels = res[0]["data"].map((x) => x.label);
const values = res
.filter((x: any) => this.selectedTypes.indexOf(x.itemId) > -1)
.map((x: any) => {
return {
seriesname: x.name,
data: x.data.map((d) => {
return {
value: d.value,
};
}),
};
});
this.typeChart.setData(labels, values);
}
},
(err) => console.log("Err")
);
}
dashboard.service.ts
getCategoryTrends(building: number, interval: intervalGroup, from:Date, to:Date): Observable<any> {
return this.dataService.get(this.config.endPoints['building-type-consumption-group'], {
startDate: from,
endDate: to,
groupId: GroupBy.MeterType,
serviceTypeId: ServiceType.ELECTRICAL,
buildingId: building,
interval: interval,
siteId: this.config.siteConfigurations.siteId,
dataMode: DataMode.CategorySum,
})
}
Get color code function (meter type is ChartGroupType.METER_TYPES for above function )
Get color code
private getColorCode(chartGroupType: ChartGroupType, itemId: number) {
let item;
let color;
switch(chartGroupType) {
case ChartGroupType.METER:
return '';
case ChartGroupType.BUILDING_CATEGORY:
item = find(this.initialService.navigationStore.buildingCategories, {buildingCategoryID: itemId});
return this.getDefaultColorCode(item);
case ChartGroupType.METER_TYPES:
item = find(this.initialService.navigationStore.meterTypes, {meterTypeID: itemId});
return this.getDefaultColorCode(item);
case ChartGroupType.HT_LOOPS:
return '';
}
}
private getDefaultColorCode(item) {
let color;
if(item === undefined || item.attributes.length === 0) {
return this.config.config.defaultColorCode;
} else {
color = find(
item.attributes,
{
textId: this.config.config.attributes.COLOR_CODE
});
console.log(item + 'chart colors are: ')
return color===null || color === undefined?this.config.config.defaultColorCode:color.value;
}
}
I'm creating a quiz that requires every answer to be answered. The problem is that you should be able to skip questions if you don't have an answer. I'm trying to set a default answer everytime I press next so when I try to skip one I don't have to answer for it to have a value. The default value I want is each time the last value of my array.
next and previous question
SetQuestion(question) {
if (this.questionNumber >= 0) {
let oldAnswerButton = document.querySelectorAll('.filter_anwser');
// Deletes old question when the next question is clicked
for (let answerButton of oldAnswerButton) {
answerButton.style.display = 'none';
}
}
this.questionNumber = question;
let q = this.quiz[question];
// Check if your at the last question so the next button will stop being displayed.
if (this.questionNumber === Quiz.length - 1) {
this.nextbtn.style.display = 'none';
this.prevbtn.style.display = 'block';
this.resultbtn.style.display = 'grid';
} else if (this.questionNumber === 0) {
this.nextbtn.style.display = 'block';
this.prevbtn.style.display = 'none';
this.resultbtn.style.display = 'none';
} else {
this.nextbtn.style.display = 'block';
this.prevbtn.style.display = 'block';
this.resultbtn.style.display = 'none';
}
// Displays Question
this.questionName.textContent = q.questionText;
this.questionName.id = "questionID";
return q;
console.log(this.getLink())
console.log(this.tmp)
}
IntoArray() {
const UrlVar = new URLSearchParams(this.getLink())
this.UrlArray = [...UrlVar.entries()].map(([key, values]) => (
{[key]: values.split(",")}
)
);
}
NextQuestion() {
// let quizUrl = this.url[this.questionNumber];
let question = this.SetQuestion(this.questionNumber + 1);
let pre = question.prefix;
let prefixEqual = pre.replace('=', '');
let UrlArr = this.UrlArray;
let UrlKeys = UrlArr.flatMap(Object.keys)
let answers = question.chosenAnswer.slice(0, -1);
this.clicked = true;
// Displays answers of the questions
for (let y = 0; y < answers.length; y++) {
let item = answers[y];
// Display answer buttons
if (UrlKeys.includes(prefixEqual)) {
console.log("exists");
let btn = document.querySelector('button[value="' + item.id + '"]');
btn.style.display = 'block';
} else {
let btn = document.createElement('button');
btn.value = item.id;
btn.classList.add("filter_anwser", pre)
btn.id = 'answerbtn';
btn.textContent = item.name;
this.button.appendChild(btn);
}
// let quizUrl = control.url[control.questionNumber];
// // console.log(this.tmp);
// if (quizUrl === undefined) {
// quizUrl.push(question.prefix[y] + '');
// }
// if (quizUrl === undefined){
// this.tmp.push('');
// }
}
this.IntoArray();
}
PrevQuestion() {
let question = this.SetQuestion(this.questionNumber - 1);
let answers = question.chosenAnswer.slice(0, -1);
// Displays answers of the questions
for (let y = 0; y < answers.length; y++) {
let item = answers[y];
// Display answer buttons
let btn = document.querySelector('button[value="' + item.id + '"]');
btn.style.display = 'block';
}
this.IntoArray();
}
Link creator:
/**
* Returns the parameters for the URL.
*
* #returns {string}
*/
getLink() {
this.tmp = [];
for (let i = 0; i < this.url.length; i++) {
// Check if question is from the same quiz part and adds a , between chosen answers and add the right prefix at the beginning
if (this.url[i].length > 0) {
this.tmp.push("" + Quiz[i].prefix + this.url[i].join(","))
// console.log(this.url)
}
if (this.url[i].length === 0) {
this.tmp.push("");
}
}
/// If answers are from different quiz parts add a & between answers.
return "" + this.tmp.join("&");
// console.log(this.url[i].prefix);
};
Answer click event
control.button.addEventListener("click", function (e) {
const tgt = e.target;
control.clicked = true;
// clear the url array if there's nothing clicked
if (control.url.length === control.questionNumber) {
control.url.push([]);
}
let quizUrl = control.url[control.questionNumber];
// Check if a button is clicked. Changes color and adds value to the url array.
if (quizUrl.indexOf(tgt.value) === -1) {
quizUrl.push(tgt.value);
e.target.style.backgroundColor = "orange";
// Check if a button is clicked again. If clicked again changes color back and deletes value in the url array.
} else {
quizUrl.splice(quizUrl.indexOf(tgt.value), 1);
e.target.style.backgroundColor = "white";
}
console.log(control.getLink());
console.log(quizUrl)
})
array:
class QuizPart {
constructor(questionText, chosenAnswer, prefix, questionDescription) {
this.questionText = questionText;
this.chosenAnswer = chosenAnswer;
this.prefix = prefix;
this.questionDescription = questionDescription;
}
}
class ChosenAnswer {
constructor(id, name) {
this.id = id;
this.name = name;
}
}
let Quiz = [
new QuizPart('Whats your size?', [
new ChosenAnswer('6595', '41'),
new ChosenAnswer('6598', '42'),
new ChosenAnswer('6601', '43'),
new ChosenAnswer('', ''),
], 'bd_shoe_size_ids=',
'The size of your shoes is very important. If you have the wrong size, they wont fit.'),
new QuizPart('What color would you like?', [
new ChosenAnswer('6053', 'Red'),
new ChosenAnswer('6044', 'Blue'),
new ChosenAnswer('6056', 'Yellow'),
new ChosenAnswer('6048', 'Green'),
new ChosenAnswer('', ''),
], 'color_ids=',
'Color isn t that important, It looks good tho.'),
new QuizPart('What brand would you like?', [
new ChosenAnswer('5805', 'Adidas'),
new ChosenAnswer('5866', 'Nike'),
new ChosenAnswer('5875', 'Puma'),
new ChosenAnswer('', ''),
], 'manufacturer_ids=',
'Brand is less important. Its just your own preference'),
]
I tried giving the array's in link creator and my eventlistener a default value and replacing it when I get and actual value from one of my buttons, but it just doesn't work. Can anybody help me?
I understand, that it might be a bit far from what you expect for an answer - but why don't you have a look at a reactive tool, like Vue? It has all the tools that you might need for such a task, and maybe more:
the whole quiz can be abstracted to a simple array of objects (the questions)
next, prev, set default answer becomes a breeze
easy to extend (with questions)
simple to update (template, features, etc.)
Vue.component('QuizQuestion', {
props: ['data', 'selected'],
computed: {
valSelected: {
get() {
return this.selected
},
set(val) {
this.$emit('update:selected', val)
}
},
},
template: `
<div>
{{ data.text }}<br />
{{ data.description }}<br />
<div class="quiz-options">
<label
v-for="val in data.options"
:key="val[0]"
>
<input
type="radio"
:name="data.text"
:value="val"
v-model="valSelected"
/>
{{ val[1] }}
</label>
</div>
</div>
`
})
new Vue({
el: "#app",
computed: {
currentQuestion() {
return this.questions[this.current]
},
hasPrev() {
return !!this.current
},
hasNext() {
return this.current < this.questions.length - 1
},
},
data() {
return {
current: 0,
questions: [{
text: 'Whats your size?',
description: 'The size of your shoes is very important. If you have the wrong size, they wont fit.',
options: [
['6595', '41'],
['6598', '42'],
['6601', '43'],
['', ''],
],
selected: null,
}, {
text: 'What color would you like?',
description: 'Color isn\'t that important, It looks good tho.',
options: [
['6053', 'Red'],
['6044', 'Blue'],
['6056', 'Yellow'],
['6048', 'Green'],
['', ''],
],
selected: null,
}, {
text: 'What brand would you like?',
description: 'Brand is less important. Its just your own preference',
options: [
['5805', 'Adidas'],
['5866', 'Nike'],
['5875', 'Puma'],
['', ''],
],
selected: null,
}, ],
}
},
methods: {
selectDefault() {
this.questions[this.current] = {
...this.questions[this.current],
selected: this.questions[this.current].options.slice(-1)[0],
}
},
getPrev() {
if (this.hasPrev) {
if (!this.currentQuestion.selected) {
this.selectDefault()
}
this.current -= 1
}
},
getNext() {
if (this.hasNext) {
if (!this.currentQuestion.selected) {
this.selectDefault()
}
this.current += 1
}
},
},
template: `
<div>
<quiz-question
:data="currentQuestion"
:selected.sync="currentQuestion.selected"
/><br />
<button v-if="hasPrev" #click="getPrev">PREV</button>
<button v-if="hasNext" #click="getNext">NEXT</button>
<button v-if="!hasNext">RESULT</button>
</div>
`
})
.quiz-options {
display: flex;
flex-direction: column;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app"></div>
EDIT
But, if frameworks/libraries are not to be used, here's a more OOP approach:
class Quiz {
constructor(questions) {
this._current = 0
this._questions = questions
}
get current() {
return this._current
}
set current(val) {
this._current = val
}
get hasNext() {
return this.current < this.questions.length - 1
}
get hasPrev() {
return !!this.current
}
get questions() {
return this._questions
}
get next() {
this.current = this.hasNext ? this.current + 1 : this.current
return this.currentQuestion
}
get prev() {
this.current = this.hasPrev ? this.current - 1 : this.current
return this.currentQuestion
}
get currentQuestion() {
return this.questions[this.current]
}
}
class Question {
constructor({
text,
description,
options,
prefix,
}) {
this.text = text
this.desc = description
this.prefix = prefix
this._options = options.map(([key, val]) => ({
id: key,
value: [key, val],
selected: false,
}))
}
get options() {
return this._options
}
set options(newOptions) {
this._options = newOptions
}
get selected() {
return this.options.find(({
selected
}) => !!selected)
}
set selected(selectedVal) {
this.options = [...this.options.map(({
value: [key, val],
selected,
...rest
}) => {
return {
...rest,
value: [key, val],
selected: key === selectedVal
}
})]
}
get lastOption() {
return this.options.slice(-1)[0]
}
setDefault() {
if (!this.selected) {
this.selected = this.lastOption.id
}
}
}
const urlParser = (quiz) => {
return quiz.questions.map(({
prefix,
selected = {
value: ['']
}
}) => {
const s = selected.value[0] ? selected.value[0] : ''
return `${prefix}${s}`
}).join('&')
}
const qArr = [{
text: 'text1',
description: 'desc1',
options: [
['1_1', '11'],
['1_2', '12'],
['1_3', '13'],
],
prefix: 'prefix_1_',
},
{
text: 'text2',
description: 'desc2',
options: [
['2_1', '21'],
['2_2', '22'],
['2_3', '23'],
],
prefix: 'prefix_2_',
},
{
text: 'text3',
description: 'desc3',
options: [
['3_1', '31'],
['3_2', '32'],
['3_3', '33'],
],
prefix: 'prefix_3_',
},
]
const getOptionsHtml = ({
text,
options
}) => {
let html = ''
options.forEach(({
id,
value,
selected
}, i) => {
html += `
<label>
<input
class="question-input"
type="radio"
name="${text}"
value="${value[0]}"
${selected ? 'checked' : ''}
/>
${value[1]}
</label>
`
})
return html
}
const getSingleQuestionHtml = (q) => {
const optionsHtml = getOptionsHtml({
text: q.text,
options: q.options
})
return `
${q.text}<br />
${q.desc}<br />
${optionsHtml}
`
}
const registerEventHandlers = ({
container,
question
}) => {
const radioBtns = document.querySelectorAll('.question-input')
radioBtns.forEach((input, i) => {
input.addEventListener('change', function(e) {
question.selected = e.target.value
})
})
}
const updateHtml = ({
container,
question
}) => {
container.innerHTML = getSingleQuestionHtml(question)
registerEventHandlers({
container,
question
})
};
const updateContainer = (container) => (question) => updateHtml({
container,
question
});
const setElDisplay = ({
el,
display
}) => {
if (display) {
el.classList.add("d-inline-block")
el.classList.remove("d-none")
} else {
el.classList.remove("d-inline-block")
el.classList.add("d-none")
}
}
const updateBtnVisibility = ({
btnNext,
btnPrev,
btnResult,
quiz
}) => () => {
setElDisplay({
el: btnNext,
display: quiz.hasNext
})
setElDisplay({
el: btnResult,
display: !quiz.hasNext
})
setElDisplay({
el: btnPrev,
display: quiz.hasPrev
})
}
(function() {
const quiz = new Quiz(qArr.map(q => new Question(q)))
const container = document.getElementById('quiz-container')
updateQuizContainer = updateContainer(container)
updateQuizContainer(quiz.currentQuestion)
const btnPrev = document.getElementById('btn-prev')
const btnNext = document.getElementById('btn-next')
const btnResult = document.getElementById('btn-result')
const updateBtns = updateBtnVisibility({
btnPrev,
btnNext,
btnResult,
quiz
})
updateBtns()
btnPrev.addEventListener('click', function() {
if (quiz.hasPrev) {
quiz.currentQuestion.setDefault()
}
updateQuizContainer(quiz.prev)
updateBtns()
})
btnNext.addEventListener('click', () => {
if (quiz.hasNext) {
quiz.currentQuestion.setDefault()
}
updateQuizContainer(quiz.next)
updateBtns()
})
btnResult.addEventListener('click', function() {
quiz.currentQuestion.setDefault()
console.log(urlParser(quiz))
})
})();
.d-inline-block {
display: inline-block;
}
.d-none {
display: none;
}
<div id="quiz-container"></div>
<div id="quiz-controls">
<button id="btn-prev" class="d-inline-block">
PREV
</button>
<button id="btn-next" class="d-inline-block">
NEXT
</button>
<button id="btn-result" class="d-none">
RESULT
</button>
</div>
<div id="result"></div>
Issue Unable to return testcaseid from array to this.filteredArray
able to return header value and all values of array if search word is empty.
help me on this.
help how to iterate testcaseid and header on search input filed.
Array -
PanelList$: any[] =
[
{
"header":"header1",
"data":[
{
"testcaseId":"tz_param",
"description":"tz_param"
},
{
"testcaseId":"tzication",
"description":"tzication"
}
]
},
{
"header":"security",
"data":[
{
"testcaseId":"tz_prompt",
"description":"tz_prompt"
},
{
"testcaseId":"z_Root_CA",
"description":"z_Root_CA"
},
{
"testcaseId":"tz_part1",
"description":"tz_part1"
}
]
}
]
input search code -
<input matInput (keyup)="applyFilter($event.target.value);" autocomplete="off" placeholder="Search Test Cases...">
Filter Function - to search header and testcase id
applyFilter(filterWord) {
let arraycase;
let arraycase1;
const word = filterWord.toString().toLowerCase();
this.filteredArray = this.PanelList$.filter(his => {
if(his.header.toString().toLowerCase() === word) {
console.log('1' + 'header')
return his}
if(his.header.toString().toLowerCase().includes(word)) {
console.log('2' + 'return full array')
return his}
his.data.filter(ids => {
if(ids.testcaseId.toString().toLowerCase() === word) {
console.log('3')
arraycase = [{header: his.header, data: [ids] }]
console.log(arraycase);
return arraycase
} {
return arraycase
}
})
console.log(arraycase1 + 'asdads');
})
Update 1 -
this.PanelList$ = JSON.parse(msg.data);
this.filteredArray = JSON.parse(msg.data);
both this.PanelList$ and this.filteredArray has same array
Final Answer to my question - i am returning the value as i am expected -
applyFilter(filterWord) {
console.log(this.PanelList$);
let arraycase;
const word = filterWord.toString().toLowerCase();
this.filteredArray = this.PanelList$.map((his) => {
if (his.header.toString().toLowerCase() === word) {
return his;
}
if (his.header.toString().toLowerCase().includes(word)) {
return his;
}
arraycase = [];
his.data.filter((ids) => {
if (ids.testcaseId.toString().toLowerCase() === word) {
arraycase = { header: his.header, data: [ids] };
console.log(arraycase);
return arraycase;
}
});
return arraycase;
});
if (this.filteredArray[0].length === 0) {
this.testCaseIdTable = true;
}
}
Since I do not have all of your code I just added some required modifications so that I can test and you can have an idea how to modify your code.
//applyFilter(filterWord) {
let arraycase;
let arraycase1;
PanelList =
[
{
"header":"TestBootNotification_CS",
"data":[
{
"testcaseId":"tc_real_module_param",
"description":"tc_real_module_param"
},
{
"testcaseId":"tc_BootNotification",
"description":"tc_BootNotification"
}
]
},
{
"header":"security",
"data":[
{
"testcaseId":"tc_with_prompt",
"description":"tc_with_prompt"
},
{
"testcaseId":"tc_install_Root_CA",
"description":"tc_install_Root_CA"
},
{
"testcaseId":"tc_install_client_cert_part1",
"description":"tc_install_client_cert_part1"
}
]
}
]
var word = "TestBootNotification_CS".toString().toLowerCase(); //filterWord.toString().toLowerCase();
this.filteredArray =
PanelList.map(
(his) => {
if(his.header.toString().toLowerCase() === word) {
console.log('1' + 'header')
return his}
if(his.header.toString().toLowerCase().includes(word)) {
console.log('2' + 'return full array')
return his}
arraycase = []
his.data.filter(ids => {
if(ids.testcaseId.toString().toLowerCase() === word) {
console.log('3')
// arraycase = [{header: his.header, data: [ids] }]
var obj = {header: his.header, data: [ids] }
arraycase.push( obj )
console.log(arraycase);
return arraycase
} else {
return arraycase
}
})
console.log(arraycase1 + 'asdads')
}
)
console.log( this.filteredArray )
I'm creating a map based on this example:
https://labs.mapbox.com/education/impact-tools/finder-with-filters/
In their example, they have two dropdown filters and one checkbox filter. I would like to have three checkbox filters. I created three checkbox filters, and on their own, they seem to work well. The issue is that the filters seem to override each other in the order clicked. In their example, the filters seem to be working together, so I can't figure out why it's not working anymore when I changed the filter type.
Here's the code for my project:
https://codepen.io/flyinginsect2/pen/eYdyqxZ
Here are snippets of the code relevant to filtering:
const config = {
style: "mapbox://styles/mapbox/light-v10",
accessToken: "pk.eyJ1IjoibGF1cmFqZWFudGhvcm5lIiwiYSI6ImNraXl5M29oMDEyMjgzM3BhNTh1MGc1NjkifQ.g4IAFIrXPpl3ricw3f_Onw",
CSV: "https://docs.google.com/spreadsheets/d/106xm254us29hAUEtR7mTo0hwbDJv8dhyQs9rxY601Oc/gviz/tq?tqx=out:csv&sheet=Attributes",
center: [-104.339, 46.869],
zoom: 2,
title: "ENVIROlocity Mapper",
description: "Environmental Networking, Volunteering, Internship, and R.... Opportunities",
sideBarInfo: ["Org_name", "CityState"],
popupInfo: ["Org_name"],
filters: [
{
type: "checkbox",
title: "Sector: ",
columnHeader: "Sector",
listItems: ["Local Government", "Nonprofit"]
},
{
type: "checkbox",
title: "Industry: ",
columnHeader: "Industry_type",
listItems: ["Conservation", "Policy"]
},
{
type: "checkbox",
title: "Internships: ",
columnHeader: "internships_YN",
listItems: ["Yes"]
}
]
};
const selectFilters = [];
const checkboxFilters = [];
function createFilterObject(filterSettings) {
filterSettings.forEach(function (filter) {
if (filter.type === 'checkbox') {
columnHeader = filter.columnHeader;
listItems = filter.listItems;
const keyValues = {};
Object.assign(keyValues, { header: columnHeader, value: listItems });
checkboxFilters.push(keyValues);
}
if (filter.type === 'dropdown') {
columnHeader = filter.columnHeader;
listItems = filter.listItems;
const keyValues = {};
Object.assign(keyValues, { header: columnHeader, value: listItems });
selectFilters.push(keyValues);
}
});
}
function applyFilters() {
const filterForm = document.getElementById('filters');
filterForm.addEventListener('change', function () {
const filterOptionHTML = this.getElementsByClassName('filter-option');
const filterOption = [].slice.call(filterOptionHTML);
const geojSelectFilters = [];
const geojCheckboxFilters = [];
filteredFeatures = [];
filteredGeojson.features = [];
filterOption.forEach(function (filter) {
if (filter.type === 'checkbox' && filter.checked) {
checkboxFilters.forEach(function (objs) {
Object.entries(objs).forEach(function ([key, value]) {
if (value.includes(filter.value)) {
const geojFilter = [objs.header, filter.value];
geojCheckboxFilters.push(geojFilter);
}
});
});
}
if (filter.type === 'select-one' && filter.value) {
selectFilters.forEach(function (objs) {
Object.entries(objs).forEach(function ([key, value]) {
if (value.includes(filter.value)) {
const geojFilter = [objs.header, filter.value];
geojSelectFilters.push(geojFilter);
}
});
});
}
});
if (geojCheckboxFilters.length === 0 && geojSelectFilters.length === 0) {
geojsonData.features.forEach(function (feature) {
filteredGeojson.features.push(feature);
});
} else if (geojCheckboxFilters.length > 0) {
geojCheckboxFilters.forEach(function (filter) {
geojsonData.features.forEach(function (feature) {
if (feature.properties[filter[0]].includes(filter[1])) {
if (
filteredGeojson.features.filter(
(f) => f.properties.id === feature.properties.id
).length === 0
) {
filteredGeojson.features.push(feature);
}
}
});
});
if (geojSelectFilters.length > 0) {
const removeIds = [];
filteredGeojson.features.forEach(function (feature) {
let selected = true;
geojSelectFilters.forEach(function (filter) {
if (
feature.properties[filter[0]].indexOf(filter[1]) < 0 &&
selected === true
) {
selected = false;
removeIds.push(feature.properties.id);
} else if (selected === false) {
removeIds.push(feature.properties.id);
}
});
});
removeIds.forEach(function (id) {
const idx = filteredGeojson.features.findIndex(
(f) => f.properties.id === id
);
filteredGeojson.features.splice(idx, 1);
});
}
} else {
geojsonData.features.forEach(function (feature) {
let selected = true;
geojSelectFilters.forEach(function (filter) {
if (
!feature.properties[filter[0]].includes(filter[1]) &&
selected === true
) {
selected = false;
}
});
if (
selected === true &&
filteredGeojson.features.filter(
(f) => f.properties.id === feature.properties.id
).length === 0
) {
filteredGeojson.features.push(feature);
}
});
}
map.getSource('locationData').setData(filteredGeojson);
buildLocationList(filteredGeojson);
});
}
function filters(filterSettings) {
filterSettings.forEach(function (filter) {
if (filter.type === 'checkbox') {
buildCheckbox(filter.title, filter.listItems);
} else if (filter.type === 'dropdown') {
buildDropDownList(filter.title, filter.listItems);
}
});
}
function removeFilters() {
let input = document.getElementsByTagName('input');
let select = document.getElementsByTagName('select');
let selectOption = [].slice.call(select);
let checkboxOption = [].slice.call(input);
filteredGeojson.features = [];
checkboxOption.forEach(function (checkbox) {
if (checkbox.type == 'checkbox' && checkbox.checked == true) {
checkbox.checked = false;
}
});
selectOption.forEach(function (option) {
option.selectedIndex = 0;
});
map.getSource('locationData').setData(geojsonData);
buildLocationList(geojsonData);
}
function removeFiltersButton() {
const removeFilter = document.getElementById('removeFilters');
removeFilter.addEventListener('click', function () {
removeFilters();
});
}
createFilterObject(config.filters);
applyFilters();
filters(config.filters);
removeFiltersButton();
I read this Mapbox documentation on combining filters, but I can't figure out how to work it in.
https://docs.mapbox.com/mapbox-gl-js/style-spec/other/#other-filter
I know there are many other Stack Exchange posts out there that address filtering on multiple criteria, but I can't find one that seems to address this specific issue.
The issue is in the space in value for "Local Government"
If you look at the generated HTML you will see a space in the id, which is not valid HTML
<input class="px12 filter-option" type="checkbox" id="Local Government" value="Local Government">
Just remove the whitespaces when building the HTML id attribute
input.setAttribute('id', listItems[i].replace(/\s/g,''));
function loadAll() {
Organization.query({`enter code here`
page: pagingParams.page - 1,
size: vm.itemsPerPage,
sort: sort(),
mapperType: 'NORMAL',
status: 'DISABLED',
search: vm.search
}, onSuccess, onError);
function sort() {
var result = [vm.predicate + ',' + (vm.reverse ? 'asc' : 'desc')];
if (vm.predicate !== 'id') {
result.push('id');
}
return result;
}
function onSuccess(data, headers) {
vm.links = ParseLinks.parse(headers('link'));
vm.totalItems = headers('X-Total-Count');
vm.queryCount = vm.totalItems;
vm.page = pagingParams.page;
vm.searchParams = PrmJson.fromJson(pagingParams.search);
// vm.organizations = data;
vm.organizations = getContractStatus(data);
}
function onError(error) {
AlertService.error(error.data.message);
}
}
function getContractStatus(organizations) {
for (var i = 0; i < organizations.length; i++) {
Contract.getByOrganizationId({
organizationId: organizations[i].id
}, function (data) {
if (data.length == 0) {
organizations[i]["contract"] = {id: 0};
} else {
organizations[i]["contract"] = {id: data.id};
}
}
);
}
return organizations;
}
When I run the code above I get the following error message:
angular.js:13920 TypeError: Cannot set property 'contract' of undefined
You are passing anonymous function, so there data and i value both are undefined .
function(data,i) {
if (data.length == 0) {
organizations[i]["contract"] = {
id: 0
};
} else {
organizations[i]["contract"] = {
id: data.id
};
}
}(data,i);
Demo
for (var i = 0; i <= 5; i++) {
demo1(i, function(k,l) {
console.log('annonymous',l)
}(i,i));
}
function demo1(val) {
console.log('demo1',val)
}