Override CSS for specific Bootstrapvue Components - bootstrap-vue

first Question here so please educate me if i'm doing this wrong.
So im working on an SPA that uses BootsrapVue and i created a view that uses a
<b-form-checkbox-group
v-model="anything"
:options="options"
:disabled="ifDisabled"
button-variant="outline-secondary"
buttons
>
when this gets rendered i get this html:
<fieldset data-v-3bacc3f3 class="form-group" id="__BVID__38">
<legend tabindex=-1" class="bv-no-focus-ring col-form-label pt-0" id="__BVID__38__label_">Selector</legend>
<div>
<div> data-v-3baac3f3 role="group" tabindex="-1" class="btn-group-toggle btn-group bv-no-focus-ring" id="__BVID__39">
<label class="btn btn-outline-secondary disabled atcive">
<input type="checkbox" name="buttons-1" disabled="disabled" class value="100" id="__BVID__39_BV_option_0">
<span>100</span>
...
now i've tried alot of stuff but cant figure out how i am able to override the scss styles for the options. Preferably only in this scope, but i cant even manage to do it globaly.
I'm even having trouble figuring out the right place where i should be looking to change css for :hover and :focus.
please help!

This works:
<style lang="scss">
.btn-group-toggle:not(#_) label {
/* general styles */
&.disabled {
}
&.focus {
}
&.active {
}
&:hover {
}
}
</style>
When adding scoped attribute to the <style> tag, you're largely at the hand of your installed pre-processor which might or might not be able to parse >>>, /deep/, ::v-deep or :deep(), depending on version.
To stay away from such issues, I use the suggestion made in Vue Loader's docs: I create a separate <style> tag for bootstrap-vue internals, without the scoped attribute and keep the rest of component style rules in a <style scoped>.
Working demo.

Related

vuetify- How do I change arrow color and the size of the icon in vuetify within text-area?

I'm trying to make a text input area like this.
I tried this way
<v-text-field
label="Outlined"
placeholder="Placeholder"
background-color="white"
append-icon="mdi-arrow-right x-large primary"
outlined
></v-text-field>
And it give me this result.
Issues are
Icon doesn't get large enough to fill the entire text-area
Can't change the color of arrow stroke
What should I do to make this text area also receives file drag and drop?(user might want to type or sometimes drop a file to the text area
Thank you so much.
Hope someone who are well knowledgeable about vuetify could help me.
for part of your question about input design and look you should use provided slot from the v-text-field component, this way you can achieve more and here is the vuetify documentation about this: text field icon slots
and to check what other slots is available for this component check this list: all text field slots
even though using slot would achieve a lot more than prop, to fully achieve the desired result you might need to overwrite some css styles that you can find by inspecting the element in the browser dev tool to find them out.
I made the look you wanted with the approach described above in the code below:
new Vue({
el: '#app',
vuetify: new Vuetify(),
})
.v-text-field.v-text-field--enclosed .v-text-field__details,
.v-text-field.v-text-field--enclosed:not(.v-text-field--rounded)>.v-input__control>.v-input__slot {
padding-right: 0 !important;
}
.v-text-field--enclosed .v-input__append-inner,
.v-text-field--enclosed .v-input__append-outer,
.v-text-field--enclosed .v-input__prepend-inner,
.v-text-field--enclosed .v-input__prepend-outer,
.v-text-field--full-width .v-input__append-inner,
.v-text-field--full-width .v-input__append-outer,
.v-text-field--full-width .v-input__prepend-inner,
.v-text-field--full-width .v-input__prepend-outer {
margin-top: 0 !important;
}
.pointer {
cursor: pointer;
}
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#4.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>
<div id="app">
<v-app>
<v-main>
<v-container>
<v-text-field label="Outlined" placeholder="Placeholder" outlined>
<template v-slot:append>
<v-sheet color="red" class="d-flex justify-center align-center rounded-r pointer" width="50" height="56">
<v-icon dark>
mdi-arrow-right
</v-icon>
</v-sheet>
</template>
</v-text-field>
</v-container>
</v-main>
</v-app>
</div>
about the drag and drop issue vuetify's v-file-input component does not natively support this behavior (for now at least) but you can read the article below to find out how to write this feature in vuetify:
Step by Step: Custom drag & drop upload component in Vuetify (Vue 2)

How can I inject a Vuetify form from a database into a template?

Apologies if this has been answered elsewhere, I have searched but not found anything as of yet.
I have a v-form stored in a database that I wish to pull back and display on a page. However, when I do so the form is not being rendered correctly. It remains as Vuetify template code and is not converted to HTML.
The form looks like this:
<v-form>
<v-container>
<v-row>
<v-col>
<div class="text-h4">Form 1</div>
</v-col>
</v-row>
<v-row>
<v-col
cols="12"
md="6"
>
<v-text-field
:counter="255"
label="Customer ID"
required
></v-text-field>
</v-col>
<v-col
cols="12"
md="6"
>
<v-text-field
label="Amount"
></v-text-field>
</v-col>
<v-col class="text-right">
<v-btn
#click="submitForm"
>
Submit
</v-btn>
</v-col>
</v-row>
</v-container>
</v-form>
I did come across a render function, but I've either not used it correctly or it is not have the desired effect - I'm a newbie at this so it may well be something simple!
The above form is pulled back from the database using axios, and the request happens in the created() function on the page where I wish to display it, using mapGetters() to grab it from the store and v-html in a v-card to show it.
Any help on this would be much appreciated.
Thanks for your time people!
How can I inject a Vuetify form from a database into a template?
You can't.
v-html docs
Updates the element’s innerHTML. Note that the contents are inserted as plain HTML - they will not be compiled as Vue templates. If you find yourself trying to compose templates using v-html, try to rethink the solution by using components instead
Another note from docs
Note that you cannot use v-html to compose template partials, because Vue is not a string-based templating engine. Instead, components are preferred as the fundamental unit for UI reuse and composition.
So in short, you cannot insert any partial template into a template of a component at runtime.
But you can create component at runtime and use it as dynamic component
const vm = new Vue({
el: '#app',
data() {
return {
downloadedTemplate: '<div> Hello </div>', // pretend this was downloaded from the server
}
},
computed: {
myDynamicComponent() {
return Vue.component('myDynamicComponent', {
template: this.downloadedTemplate
})
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<component :is="myDynamicComponent" />
</div>
Note that to do this, you must use Vue distribution which includes the template compiler
I don`t know about your particular use case, but unless you are working with tens of different forms, storing templates in database sounds like a sub-optimal strategy - a lot of unnecessary work and hard to mainain

Vue.js: Is there a way to have #submit.prevent on all the forms of a project?

I'm realizing there are some snippets that I'm repeating everytime, and sometimes I forget.
One of them is the #submit.prevent. In all forms I have to write it for preventing to submit, I'll always manage the submission through a vue method.
So can I do something that all forms have this instruction implicitly?
You can create a simple (probably functional) component and use this instead of the normal <form>.
// BaseForm.vue
<template>
<form #submit.prevent="onSubmit">
<slot />
</form>
</template>
<script>
export default {
props: {
onSubmit: {
type: Function,
required: true,
}
}
}
</script>
You won't really save a lot of code, but you won't have to think about it anymore. You could include the basic <button type=submit></button> in here as well.

post form data to rest api from Ember component

I'm trying to post data from an input and a button group in a component using Ember to my REST API using the actions up method, but the code is confusing me a bit and I haven't found a clear example of how to do it.
The site is a tracker for competitive games in Overwatch, so enter the rank after the game and see it in a list. There is one table, and one endpoint with no children in the API. Basically a simple to-do app, but i'm using components to keep everything modular. I also want to add edit and delete, but that is out of scope for this question.
app/templates/components/add-game.hbs
<form class="form-inline">
<div class="form-group">
<label class="control-label">
Rank <small>(After match)</small>
{{input value=rank type="number" min="4" class="form-control"}}
</label>
</div>
<div class="form-group">
<label class="control-label">
Outcome
{{#bs-button-group value=outcome type="radio" onChange=(action (mut outcome)) as |bg|}}
{{#bg.button type="default" value='W'}}Win{{/bg.button}}
{{#bg.button type="default" value='D'}}Draw{{/bg.button}}
{{#bg.button type="default" value='L'}}Loss{{/bg.button}}
{{/bs-button-group}}
</label>
</div>
<div class="spacer"></div>
<div class="form-group">
<button {{action 'saveGame'}} type="submit" class="btn btn-default btn-primary">Save</button>
</div>
</form>
app/components/add-game.js
import Ember from 'ember';
export default Ember.Component.extend({
actions: {
saveGame() {
const outcome = this.get('model.outcome');
const rank = this.get('model.rank');
console.log(outcome);
console.log(rank);
}
}
});
app/application.hb
{{nav-bar}}
<div class="container-fluid">
<div class="row">
<div class="col-md-offset-2 col-sm-8 col-md-8 main">
{{add-game}}
<br>
{{game-table model=model.games}}
</div>
</div>
</div>
{{outlet}}
I feel like I have most of it there, im just missing a few things with the Data Down, Actions Up approach that Ember uses, but haven't found a clear example to work off that is similar to my code. As you can probably tell I've got the code sending the data to the console, but im not sure of the best way to send it up to the route to then be sent to the server. I think I need to use the model, but the specific code
I am using ember-bootstrap for the styling and custom button group component.
The whole project is on Github
You can get an overview of DDAU architecture of Ember here. When you want to send the action up to the parent to handle, you have to notify the component of the action where you want to pass out any event. Here in your case, if you want to handle the action saveGame in the parent (application), then you have to pass the action to the component add-game while invoking the component as below:
**Application.hbs**
{{game-table model=model.games saveGameInParent=(action 'saveGameInParent')}}
where saveGameInParent is the action present in the application controller. In the component, you need to call out this action explicitly to pass out the control from the component to parent.
**component/add-game.js**
import Ember from 'ember';
export default Ember.Component.extend({
actions: {
saveGame() {
// do you really mean to access these props from model??
const outcome = this.get('model.outcome');
const rank = this.get('model.rank');
this.saveGameInParent(outcome, rank);
}
}
});
And finally, in you application controller, there should be action named, saveGameInParent to handle the bubbled up action from the component.
**controllers/application.js**
actions: {
saveGameInParent(outcome, rank) {
// post your result to the server using any network library.
}
}
PS: It looks like you have mentioned rank and outcome as your direct component property in the component's template file. but in the saveGame action, you tried to access those from model, which you cannot do.

CQ5 Sightly Accordion component

Hi am trying to design an accordion component using sightly in AEM where instead of jsp we write html code along with different file for css and js under client libs.
I simply coded the below written part and wrote js for the same but am not able to see any changes ... Could someone please provide me a solution to implement the same.. ->when i click on show a parsys section opens up and when show converts to hide and when i click on hide the parsys section closes and hide converts to show.
<div data-sly-use.clientLib="${'/libs/granite/sightly/templates/clientlib.html'}" data-sly-unwrap>
<css data-sly-call="${clientLib.css # categories=['sd-singtel.accordion_2']}" data-sly-unwrap/>
<js data-sly-call="${clientLib.js # categories=['sd-singtel.accordion_2']}" data-sly-unwrap/>
</div>
<div data-sly-test="${wcmmode.edit}">Accordion_2 component</div>
<div class="about-contentcontainer">
<div class="about-content">
<div class="awards">
<h4> <span class="more">Show</span></h4>
<h4> <span class="more expanded">Hide</span></h4>
</div>
</div>
</div>
<script>// <![CDATA[
$(document).ready(function() {
alert("Hello");
$(".awards h4 a").click(function() {
enter code here
$(this).parent().next().slideToggle("slow");
var htmlStr = $(this).find(".more").html();
if (htmlStr == "Show") {
$(this).find(".more").html("Hide");
$(this).find(".more").addClass("expanded");
} else {
$(this).find(".more").html("Show");
$(this).find(".more").removeClass("expanded");
}
});
});
// ]]></script>
Looking at it, I think that this has little to do with Sightly or even with AEM. Also, I'm not sure which content you want to toggle.
Below's a working HTML fragment for toggling content (independent from AEM):
<style>
.toggle-content {
display: block;
}
.toggle-content-hide,
.toggle-content-hidden .toggle-content-show {
display: inline;
}
.toggle-content-show,
.toggle-content-hidden .toggle-content-hide {
display: none;
}
</style>
<a href="#" class="toggle-content">
<span class="toggle-content-show">Show</span>
<span class="toggle-content-hide">Hide</span>
</a>
<div>Sample content 1</div>
<a href="#" class="toggle-content">
<span class="toggle-content-show">Show</span>
<span class="toggle-content-hide">Hide</span>
</a>
<div>Sample content 2</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script>
jQuery(function($) {
$('.toggle-content').click(function () {
$(this).toggleClass('toggle-content-hidden').next().toggle('slow');
return false;
})
});
</script>
To implement this in AEM, you should place the inline CSS into a CSS file of a client library, and the inline JS into a JS file of a client lib. I usually recommend to place them in the same client library within the component itself, so that everything that relates to that component is in the same folder. But when doing so, it is important to keep in mind that on a publish server, all /apps requests are forbidden by the dispatcher for security reasons, so all client libraries located under /apps should be merged and minified as one file that is typically located somewhere under /etc. To do so, you can use following repository node structure:
/apps/
mysite/
components/
mycomponent/
mycomponent.html Sightly template
clientlib/
jcr:primaryType = cq:ClientLibraryFolder
categories = [mysite.mycomponent]
css.txt contains just a reference to style.css
style.css contains the style snippet
js.txt contains just a reference to script.css
script.js contains the script snippet
/etc/
designs/
mysite/
clientlib/
jcr:primaryType = cq:ClientLibraryFolder
categories = [mysite.publish]
embed = [mysite.mycomponent, ...]
dependencies = [mysite.jquery]
The embed property of the /etc clientlib will make that it embeds and merges within the same file all clientlibs that are listed there. As opposed to the client libraries listed under the dependencies property, which will not get merged and will be served as a separate file. You can play with these properties to build the structure you need to optimize your site. There are also settings to automatically minify or not these files.
On the page, you then include the mysite.publish master clientlib located under /etc. So your page <head> element, would contain something like following Sightly template:
<head data-sly-use.clientLib="/libs/granite/sightly/templates/clientlib.html">
<sly data-sly-call="${clientLib.all # categories='sd-singtel.accordion_2'}" data-sly-unwrap/>
</head>
If you're using AEM 6.1, you can even drop the data-sly-unwrap, because the <sly> tag has the same effect.
After that, the Sightly template of your component located under a path like /apps/mysite/components/mycomponent/mycomponent.html would look as follows:
<div data-sly-test="${wcmmode.edit}">mycomponent name</div>
<a href="#" class="toggle-content">
<span class="toggle-content-show">Show</span>
<span class="toggle-content-hide">Hide</span>
</a>
<div>${properties.myContentProperty}</div>