Set the active item in a custom group list component - vue.js

EDIT Here is a codepen of my current component:
https://codepen.io/Gecko29/pen/XWdZPpj
I am trying to use the vuetify list component to create a folder like structure in my application. I have an object like so:
listOfItems = {item1 : {
expanded = true,
subList = [item, item...]
},
item2 : {....
My current code to display each parent item along with the sublist items can be found here:
https://codepen.io/Gecko29/pen/XWdZPpj
This works with the list displayed and being able to toggle the hiding and showing of containing list items.
I now wish to be able to set a sublist item as being active. To do this I have a variable that stores the active sublist name. If containingItem == activeItem, I wish for this item to be highlighted as if it were selected. What would be the best way of achieving this?

The simplest one is that you can wrap {{containingItem}} value inside a div or a span. Then check the condition to add the active class or not to that div. For example, I check containingItem equal "x":
<v-list-item-subtitle>
<div :class="containingItem === 'x'? 'active': ''">{{containingItem}}</div>
</v-list-item-subtitle>

Related

Accordion has a default active panel, but it won't open

I am using a frontend library called Element UI to create some accordions on my website. I got an array of objects that I like to create accordions for. FYI, from the element ui website: the v-model used on the accordion specifies the currently active panel. The name attribute is the unique identification of the panel. That means I can do:
<el-collapse v-model="activeName" accordion>
<el-collapse-item title="Consistency" name="1">
<div>content content content</div>
</el-collapse-item>
<el-collapse-item title="Consistency" name="2">
<div>more content more content more content</div>
</el-collapse-item>
</el-collapse>
One this loads, the first accordion will open since in the data object, activeName is set to 1:
data() {
return {
activeName: '1',
}
}
Now I thought I'd just loop through the array and create accordions for the items in my array, and binding the name attribute to the index + 1, so that the first item will have the name attribute equal to 1, the second to 2 etc. So:
<el-collapse v-model="activeName" accordion>
<el-collapse-item
v-for="(item, index) in experience"
:title="item.company"
:name="index + 1"
:key="index"
>
<div> content content content </div>
</el-collapse-item>
</el-collapse>
But for some reason, when the page loads, the first item in the accordion won't open automatically. They're all closed by default. I created a codesandbox with the problem that you can see for yourself here: codesandbox
The problem is that when you run a for loop and assign name, it's a number and not a string.
:name="index+1" <---- This is a number
But, activeName is a string. So, the values don't match and that's why the accordian does not open on page load.
Here's an updated sandbox: https://codesandbox.io/s/vue-template-ysm79
I changed activeName to a number. The for loop accordian will now open and the normal HTML accordians won't.

VueJS: Pass data from template element to another

In my app I've got some card elements printed dynamically from an array of data. I wanted these cards to open an action sheet on click, that would display an image url from the same array element.
<f7-button class="img-trigger" #click="$refs.actionsOneGroup.open()">
<f7-card v-for="npc in npcs" :key="npc.npcId" class="boss-card-container">
<f7-card-header class="no-border boss-card subheading no-hairline" valign="bottom" :style="'background-image:url(' + npc.npcImg + ');'">
{{ npc.npcName }}
</f7-card-header>
</f7-card>
</f7-button>
<f7-actions class="img-container" ref="actionsOneGroup">
<f7-actions-group v-for="npc in npcs" :key="npc.npcId">
<img :src="npc.npcImg" class="boss-image">
</f7-actions-group>
</f7-actions>
As you can see here, I iterate through the npc array to print the f7-card elements, and on the cards I show a small preview of the npc.npcImg image. What I would like to do is show that same image inside the action sheet. For now I just iterate through the array again separately, which of course results in all the images printing inside the same element, as expected.
I'm not sure how to link the two together and pass the npc.npcImg down to the action sheet component.
Help is much appreciated.
I don't know about the framework7, but in vue.js you have to use this array item as source to display the image. You can pass it as parameter on the refs.actionsOneGroup.open() function and store it in a variable to use it after. In the example I saved the npc in the selectedNpc variable. Your code will looks like it:
<f7-button class="img-trigger">
<f7-card v-for="npc in npcs" :key="npc.npcId" class="boss-card-container" #click="$refs.actionsOneGroup.open(npc)">
<f7-card-header class="no-border boss-card subheading no-hairline" valign="bottom" :style="'background-image:url(' + npc.npcImg + ');'">
{{ npc.npcName }}
</f7-card-header>
</f7-card>
</f7-button>
<f7-actions class="img-container" ref="actionsOneGroup">
<f7-actions-group v-if="selectedNpc">
<img :src="selectedNpc.npcImg" class="boss-image">
</f7-actions-group>
</f7-actions>
I created a codepen to show you how to do it in vue.js

Disable p-dropdown depending selection of another p-dropdown PrimeNG

I am using PrimeNG in my angular app, I have issue with p-dropdown
Question
I have two dropdowns for country and caste_category, I provide caste_reservation for only India , in case of other country selection , the OPEN option from caste_category needs to get selected and make the disable that dropdown.
If I have well understood your need, you have to set onChange event on country dropdown. This event will call a method that will trigger disabled property on caste dropdown depending on the country selected. It will also select OPEN option on this dropdown if the country is not India.
HTML
<p-dropdown [options]="countries" [(ngModel)]="applicant.country" (onChange)="updateCountry()"></p-dropdown>
<p-dropdown [options]="castes" [(ngModel)]="caste" [disabled]="disableCasteDropdown"></p-dropdown>
TS
updateCountry() {
if(this.applicant.country!=='India') {
this.disableCasteDropdown = true;
this.caste = 'o';
} else {
this.disableCasteDropdown = false;
this.caste = null;
}
}
See Plunker
Is it what you're looking for ?
If you are using Directive form controls you can disable the input, dropdown etc... by adding disabled: true in the form control
Using disabled attribute in html results to this message in console :
It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
you. We recommend using this approach to avoid 'changed after checked' errors.
Example:
form = new FormGroup({
first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
last: new FormControl('Drew', Validators.required)
});

How to show/hide div in WinJS Template dynamically

I have a Windows 8 app with a template that contains a div I want to show or hide based on the value of a property inside a data-win-control="WinJS.Binding.Template". I have tried the following without luck:
<div data-win-bind="visible: isMore"> ..content... </div>
where isMore is a boolean property of the databound item.
How can I do that? I guess the visible property does not exist?
You are right - the visible property doesn't exist, but you can control the appearance using CSS and a binding converter.
First, use WinJS.Binding.converter to create a converter function that translates a boolean to a value value for the CSS display property, like this:
var myConverter = WinJS.Binding.converter(function (val) {
return val ? "block" : "none";
});
Make sure that the function is globally available - I use WinJS.Namespace.define to create collections of these converters that I can get to globally.
Now you can use the converter in your data binding to control the CSS display property, like this:
<div data-win-bind="style.display: isMore myConverter"> ..content... </div>

Dojo disable all input fields in div container

Is there any way to disable all input fields in an div container with dojo?
Something like:
dijit.byId('main').disable -> Input
That's how I do it:
dojo.query("input, button, textarea, select", container).attr("disabled", true);
This one-liner disables all form elements in the given container.
Sure there is. Open up this form test page for example, launch FireBug and execute in the console:
var container = dojo.query('div')[13];
console.log(container);
dojo.query('input', container).forEach(
function(inputElem){
console.log(inputElem);
inputElem.disabled = 'disabled';
}
)
Notes:
On that test page form elements are actually dijit form widgets, but in this sample I'm treating them as if they were normal input tags
The second dojo.query selects all input elements within the container element. If the container had some unique id, you could simplify the sample by having only one dojo.query: dojo.query('#containerId input').forEach( ...
forEach loops through all found input elements and applies the given function on them.
Update: There's also a shortcut for setting an attribute value using NodeList's attr function instead of forEach. attr takes first the attribute name and then the value or an object with name/value pairs:
var container = dojo.query('div')[13];
dojo.query('input', container).attr('disabled', 'disabled');
Something else to keep in mind is the difference between A Dijit and a regular DomNode. If you want all Dijit's within a DomNode, you can convert them from Nodes -> Dijit refs with query no problem:
// find all widget-dom-nodes in a div, convert them to dijit reference:
var widgets = dojo.query("[widgetId]", someDiv).map(dijit.byNode);
// now iterate over that array making each disabled in dijit-land:
dojo.forEach(widgets, function(w){ w.attr("disabled", "disabled"); }
It really just depends on if your inputs are regular Dom input tags or have been converted into the rich Dijit templates (which all do have a regular input within them, just controlled by the widget reference instead)
I would do it like this:
var widgets;
require(["dijit/registry", "dojo/dom"], function(registry, dom){
widgets = registry.findWidgets(dom.byId(domId));
});
require(["dojo/_base/array"], function(array){
array.forEach(widgets, function(widget, index) {
widget.set("disabled", true);
});
});
Method findWidgets is essential to get all widgets underneath a specific DOM.