I am trying to implement a hierarchical category menu with Algolia's searchHelper.js, but the category content is not showing.
https://jsfiddle.net/t0tue5rk/1/
Sample Algolia record:
objectID: 41
title: "Canon 40D With Lens"
hierarchicalCategories: {
"lvl0" : "Video Juegos y Consolas",
"lvl1" : "Video Juegos y Consolas > PS3",
"lvl2" : "Video Juegos y Consolas > PS3 > Juegos"
}
The hierarchical facets are different from the conjunctive and disjunctive facets in that they are based on a tree. The problem in your example is that you reuse the same kind of template for this different structure. You can find more information about the manipulation of hierarchical facets on the main documentation of the Algolia JS Helper.
I also fixed your sample on jsFiddle. Here are the parts that I changed:
Handling the hierarchical facets when receiving data (l.128):
else if(facetName === 'categories') {
facetContent = {
facet: facetName,
title: FACETS_LABELS[facetName],
values: content.getFacetValues(facetName, {sortBy: ['isRefined:desc', 'count:desc']})
};
facetsHtml += hierarchicalFacetTemplate.render(
facetContent,
{sub: hierarchicalFacetTemplateSource});
}
For the sake of simplicity, I hardcoded the name of the attribute.
Create two templates, one for the container and one for the recursively going through the tree of values. (html: l.117-138)
<script type="text/template" id="hierarchical-facet-header-template">
<div class="facet facet-hierarchical">
<h5>{{ title }}</h5>
{{#values}}
{{>sub}}
{{/values}}
</div>
</script>
<!-- Hierarchical Facet template -->
<script type="text/template" id="hierarchical-facet-template">
<ul>
{{#data}}
<li>
<a href="" class="facet-link toggle-refine facet-hierarchical {{#isRefined}}facet-refined{{/isRefined}}" data-facet="{{ facet }}" data-value="{{ path }}">
{{ name }}<span class="facet-count">{{ count }}</span>
</a>
{{>sub}}
</li>
{{/data}}
</ul>
</script>
Import those new templates to the JS. (js: l.44-46)
var hierarchicalFacetHeaderTemplateSource = $('#hierarchical-facet-header-template').text();
var hierarchicalFacetTemplateSource = $('#hierarchical-facet-template').text();
var hierarchicalFacetTemplate = Hogan.compile(hierarchicalFacetHeaderTemplateSource);
Related
I'm using InstantSearch.js (via algolia) to make a price rangeslider. It's ok and it works well with one exception: the prices overlap when they are too close.
We can see it on several examples, even on the site of the doc:
Doc algolia
I use it for vehicle prices so we don't see anything when don looks for vehicles with prices not far apart
I would simply like to leave the 2 rheostat-tooltip fixed but I can't find a way to do it. (the prices don't move, but the cursors do)
You can see my problem here :
As #cmgchess suggested in comment I post a link where there is an example : example instantSearch and where you can easily see the overlapping.
thanks for any time and help :)
HTML
<li class="u-bt-thin-translucid">
<button class="my-grid mod-space-between mod-middle my-text mod-ff-lead-bold-2 mod-fs-sm2 mod-uppercase u-pt-sm u-pb-sm u-c-neutral-dark-2 u-bc-neutral-light-max u-w-100 u-b-none"
my-toggle="dd-filtrer-par-prix-mensualite"
my-toggle-options="force_dismiss"
u-pr-xxs="sm,md">
<span class="mod-on icon-chevron-up u-fs-lg"></span>
<span class="mod-off icon-chevron-down u-fs-lg"></span>
</button>
<div class="u-pb-sm" my-toggle-name="dd-filtrer-par-prix-mensualite">
<div class="my-text mod-uppercase">Prix</div>
<div id="price-range" class="u-pl-sm u-pr-md u-mb-md"></div>
<div class="my-text mod-uppercase">Mensualité (€/mois)</div>
<div id="monthly-price-range" class="u-pl-sm u-pr-md"></div>
</div>
</li>
JS
// Filtre prix
if (document.querySelector('#price-range') !== null) {
algoliaBmc.search.addWidgets([
instantsearch.widgets.rangeSlider({
container: '#price-range',
attribute: 'price',
precision: 0,
step: isGoa ? 10 : 1000,
pips: false,
tooltips: true
})
]);
}
as I'm on my Vue spree (started recently but so far I'm really enjoying learning this framework) couple of questions rised up. One of which is how to post form from multiple components. So before I continue forward I wanted to ask you what are you thinking about this way of structuring and point me in right direction if I'm wrong.
Here it goes.
I'm working on a SPA project using ASP.NET CORE 2.1 and Vue JS Template (with webpack)(https://github.com/MarkPieszak/aspnetcore-Vue-starter) and my project is structured in several containers, something like this:
In my app-root i registered several containers
<template>
<div id="app" class="container">
<app-first-container></app-first-container>
<app-second-container></app-second-container>
<!--<app-third-container></app-third-container>-->
<app-calculate-container></app-calculate-container>
<app-result-container></app-result-container>
</div>
</template>
<script>
// imported templates
import firstContainer from './first-container'
import secondContainer from './second-container'
import calculateContainer from './calculateButton-container'
//import thirdContainer from './third-container'
import resultContainer from './result-container'
export default {
components: {
'app-first-container': firstContainer,
'app-second-container': secondContainer,
// 'app-third-container': thirdContainer,
'app-calculate-container': calculateContainer,
'app-result-container': resultContainer
}
}
</script>
In my first container I'm having several dropdowns and two input fields with my script file where I'm fetching data from API and filling dropdowns and input fields with fetched data.
Something like this ( entered some dummy code for demonstration)
<template>
<div>
<h1>Crops table</h1>
<p>This component demonstrates fetching data from the server. {{dataMessage}}</p>
<div class="form-row">
<div class="form-group col-md-6">
<label for="exampleFormControlSelect1" class="col-form-label-sm font-weight-bold">1. Some text</label>
<select class="form-control" id="exampleFormControlSelect1" v-model="pickedCropType" #change="getCropsByType()">
<option v-for="(cropType, index) in cropTypes" :key="index" :value="cropType.id" :data-imagesrc="cropType.imgPath">{{ cropType.name }}</option>
</select>
</div>
<div class="form-group col-md-6">
<label for="exampleFormControlSelect2" class="col-form-label-sm font-weight-bold">2. Some text</label>
<select class="form-control" id="exampleFormControlSelect2">
<option v-for="(crop, index) in cropSelectList" :key="index" :value="crop.id">{{ crop.name }}</option>
</select>
</div>
</div>
</div>
</template>
<script>
import { mapActions, mapState } from 'vuex'
export default {
data() {
return {
cropTypes: null,
cropSelectList: null,
crops: null,
pickedCropType: null,
}
},
methods: {
loadPage: async function () {
try {
//Get crop types and create a new array with crop types with an added imgPath property
var cropTypesFinal = [];
let responseCropTypes = await this.$http.get(`http://localhost:8006/api/someData`);
responseCropTypes.data.data.forEach(function (element) {
cropTypesFinal.push(tmpType);
});
} catch (err) {
window.alert(err)
console.log(err)
}
},
getCropsByType: async function () {
//Get crops by crop type
let responseCrops = await this.$http.get(`http://localhost:8006/api/crop/Type/${this.pickedCropType}`);
var responseCropsData = responseCrops.data.data;
this.cropSelectList = responseCropsData;
}
},
async created() {
this.loadPage()
}
}
</script>
And in my second container I have different dropdowns and different input fields with different scripts etc.
So, my questions are:
1.) I'm having required data form field in first container and in second container I'm having additional data and my submit button is separated in third container (app-result-container). So, is this proper and logical way of structuring containers if not can you point me in right direction?
2.) Is it smart to input script tag in every container where I'm processing/fetching/submitting some data for that particular container? Should I put scripts tag in separated file and keep structure clean, separating html from js file.
Example:
import { something } from 'something'
export default {
data () {
return {
someData: 'Hello'
}
},
methods: {
consoleLogData: function (event) {
Console.log(this.someData)
}
}
}
3.) Can I send input values from one container to another (In my particular case from first and second container to app-calculate-container(third container))?
How to on submit return results container with calculated imported values
If you want components to communicate or share data with one another, you will need to either emit an event from one component up to the parent and pass it down via props, or use some kind of state management model, like Vuex, where each of your components can listen to the store.
Take a look at this code sandbox: https://codesandbox.io/s/8144oy7xy2
App.vue
<template>
<div id="app">
<child-input #input="updateName" />
<child-output :value="name" />
</div>
</template>
<script>
import ChildInput from "#/components/ChildInput.vue";
import ChildOutput from "#/components/ChildOutput.vue";
export default {
name: "App",
components: {
ChildInput,
ChildOutput
},
data() {
return {
name: ""
};
},
methods: {
updateName(e) {
this.name = e.target.value;
}
}
};
</script>
ChildInput.vue
<template>
<input type="text" #input="changeHandler">
</template>
<script>
export default {
name: "ChildInput",
methods: {
changeHandler(e) {
this.$emit("input", e);
}
}
};
</script>
ChildOutput.vue
<template>
<p>{{ value }}</p>
</template>
<script>
export default {
name: "ChildOutput",
props: {
value: {
type: String,
default: ""
}
}
};
</script>
What's going on?
The ChildInput component is a text field and on every change inside it, fires an event (emits using this.$emit() and passes the whole event up).
When this fires, App is listening to the change, which fires a method that updates the name data property.
Because name is a reactive data property and is being passed down as a prop to the ChildOutput component, the screen re-renders and is updated with the text written.
Neither ChildInput nor ChildOutput knows about one another. It's the parent that listens to the event passed to it, then passes the new prop down.
This way of working is fine and simple to understand, but I would strongly recommend looking at Vuex, as this method can get messy and complicated when you go beyond trivial tasks.
I have 2 components:
x-container and x-item.
they have a hierarchy similar to < table > and < tr > or to < tr > and < td >...
Hence x-item components are only effective when they're inside an x-container component:
<x-container>
<x-item></x-item>
</x-container>
I want to pass an attribute value from x-container to x-item:
<x-container att="value">
<x-item></x-item>
</x-container>
In this case I need value to be visible to x-item - is it possible?
Thanks!
It works out of the box if you know the structure of x-container beforehand (JSBin):
<polymer-element name="x-container" attributes="value">
<template>
<x-item value="{{value}}"></x-item>
</template>
<script>
Polymer('x-container', {
value : null,
ready: function() {
}
});
</script>
</polymer-element>
<polymer-element name="x-item" attributes="value">
<template>
<div>x-item value:{{value}}</div>
</template>
<script>
Polymer('x-item', {
});
</script>
</polymer-element>
<x-container value="test"></x-container>
If you want to dynamically create the relationship of x-container and x-item refer to these SO threads:
Data-binding between nested polymer elements
Using template defined in light dom inside a Polymer element
What is the best way to implement declarative collection rendering with Polymer?
I am using Kendo UI Grid and I have configured it to use popup editing with custom template
<script id="popup_editor" type="text/x-kendo-template">
<div id="editor">
<div class="k-edit-label">
<label for="Type">Type</label>
</div>
<select data-role="dropdownlist" data-value-field="Type" data-text-field="Type"
data-bind="source: typeSource, value: selectedProduct"></select>
<div class="k-edit-label">
<label for="Type">Option</label>
</div>
<select data-role="dropdownlist" data-value-field="Option" data-text-field="Option"
data-bind="source: productsSource.Options, value: selectedOption"></select>
</div>
</script>
This is my ViewModel:
function ViewModel() {
var getTypesUrl = "/Controller/Action";
var viewModel = kendo.observable({
typeSource: new kendo.data.DataSource({
transport: {
read: {
url: getConditionTypesUrl,
dataType: "json"
},
},
batch: true,
schema: {
model: {
id: "Type"
}
}
}),
selectedType: null,
selectedOption: null
});
kendo.bind($("#editor"), viewModel);
}
ViewModel();
My action returns JSON.
The problem is that when I click on the "Add new record" button, there is no call to the getTypesUrl and the dropdownlist is not populated. The general idea is to have different options for different types and to populate the Option dropdownlist depending on the selected type. I believe, that the problem occurs because the editor is showed only when the button is clicked and the kendo can not create the bindings.
If the Drop down list is the same for each row get its values from the Data Source and store these in a variable in the page in JavaScript and point the Drop Down list at this new Data Source. Use some JavaScript to associate the id and name.
Alternatively if this is loaded based on some other logic implement a separate call to populate the Data source for the drop down list in your view model.
http://www.aspnetwiki.com/page:introduction-to-kendo-mvvm
http://www.aspnetwiki.com/page:kendo-mvvm-ui-grid
Further note your can write your template purely in JavaScript and bind this to the html, advantage of which is you can debug it and it can still be loaded by an ajax call later and it is likely going to be smaller.
I need to extract "https://www.somesite.com/Some.Name.123" from the code below.
That code segment is repeated many times, and I need the URLs ..Some.Name.X.
There are other code segments between each of the ones I'm interested in, with very different surrounding html. I don't need the ..Some.Name.x URLs in those other segments.
The following is unique to what URLs I need: "<a class="-cx-PRIVATE-uiImageBlock__image"
<div class="clearfix pvm">
<a class="-cx-PRIVATE-uiImageBlock__image -cx-PRIVATE-uiImageBlock__largeImage lfloat"
aria-hidden="true" tabindex="-1" href="https://www.somesite.com/Some.Name.123">
I don't know how to tag that preceding HTML with iMacros, or how to do that with jQuery as the structure will a bit different each time, but you could to this.
Save the web pages with iMacros. Write a program (c, etc.) to read each of the saved files and write the URLs that follow "cx-PRIVATE-uiImageBlock__image" to a file. Add that list of URLs to an iMacro, or have iMacros read the file, and then process each URL from iMacros.
You need to use some scripting.
My answer makes use of jQuery
var listoflinks = []; //array containing your links
$('a[href*="somesite.com"]').each(function () { // for each link that contains somesite.com in href
var j = $(this).attr('href'); //put the whole href in a variable
listoflinks.push(j); // put all values in an array
});
you'll end up with an array that contains all the href values you're looking for.
If you want to see an example and/or you want to play around with the script you can go here:
http://jsfiddle.net/flish/rESjg/
Edited
Your code is still not clear enough, but hopefully this may help
<a class="sibling a" href="link">sibling a</a><br />
<div class="sibling div"><br />
<a class="child a" href="start-with-link/correct-link">Child a</a><br />
</div><br />
Above is the markup I've used. What this means is that I have considered that you have the following elements:
a // with a sibking div
div // with a child a
a // and all of them have appropriate classes
For this markup you can use the following code (jQuery, of course)
var listoflinks = []; //array containing your links
$('a[class="sibling a"]').siblings('div[class="sibling div"]').children('a[class="child a"]').each(function () {
if ((($(this).attr("href")).substring(0,15))=="start-with-link"){
var i = $(this).attr("href");
listoflinks.push(i);
}
});
View detailed example at http://jsfiddle.net/flish/HMXDk/
Be that as it may, you can add more sibling and children elements in case you have other html entities you forgot to mention
<a class="-cx-PRIVATE-uiImageBlock__image" ------------------ <div class="clearfix pvm"> <a class="-cx-PRIVATE-uiImageBlock__image -cx-PRIVATE-uiImageBlock__largeImage lfloat" aria-hidden="true" tabindex="-1" href="somesite.com/some.name.123">
For example, what means ------------------ in your code above?