ng-bootstrap NgbModalOptions are ignored when passing a Component to the open function - ng-bootstrap

when passing a Component parameter to the modalService.open function, the options are ignored. For instance, following example doesn't work:
const modalRef = this.modalService.open(MyModalComponent, { size: 'lg' });
reference to the examples page that shows how it should work:
https://ng-bootstrap.github.io/#/components/modal/examples
Example of the problem at stackblitz:
https://stackblitz.com/edit/angular-gr86pa?file=src/app/modal-component.ts

Related

Flags inside a React Bootstrap select option renders as [object, object]

I want to display Flags icons inside a React Bootstrap selection Option. I have tried both CSS based and React based libraries to do so and in each case I get only [object object]
I have tried with the https://github.com/lipis/flag-icon-css CSS library
<Form.Control as="select">
<option><span className="flag-icon flag-icon-gr"></span></option>
</Form.Control>
Which gives me a warning and the same [Object object]
Warning: Only strings and numbers are supported as <option> children.
I have also attempted with the React wrapper for the same library https://www.npmjs.com/package/react-flag-icon-css
<Form.Control as="select">
<option><FlagIcon className="countryIcon" code="us" size="lg"/></option>
</Form.Control>
Which does not generate a warning but no results either
Does anyone know how I can get something else than string or number in the Option, or another way to include an icon ?
Option HTML tag accepts text only, it can't accept any other HTML, it will strip it. You can check this React issue [bug][16.5.0] option returns [object Object] instead of string and read the comment by Dan Abramov:
I don't think it was strictly a regression. This is kind of a thorny
area. It was never intentionally supported. It accidentally worked on
initial mount but then crashed on updates (#13261). Fixing the crash
was more important, so we fixed it to be treated as text content
(which it should be). Unfortunately this means putting custom
components in the middle is not supported. That's consistent with how
textarea and similar elements work.
I think it's better to show invalid output and warn about something
that breaks on updates, than to let people use it only to discover it
crashes in production. But I can see arguments for why this should be
supported when the custom component returns a string. Unfortunately I
don't know how to fix it in a way that would both solve the update
crashes and support text-only content. I think for now it's reasonable
to say putting custom components into doesn't really work
(and never quite worked correctly), and ask you to manually provide a
string to it.
Alternatively, you can use Bootstrap Dropdowns to create a dropdown button with a list of countries using the code below:
App.js:
...
import Dropdown from 'react-bootstrap/Dropdown';
import FlagIcon from './FlagIcon.js'
function App() {
const [countries] = useState([
{ code: 'gr', title: 'Greece'},
{ code: 'gb', title: 'United Kingdom'},
{ code: 'us', title: 'United States'}
]);
const [toggleContents, setToggleContents] = useState("Select a country");
const [selectedCountry, setSelectedCountry] = useState();
return (
<div className="App">
<Form>
<Dropdown
onSelect={eventKey => {
const { code, title } = countries.find(({ code }) => eventKey === code);
setSelectedCountry(eventKey);
setToggleContents(<><FlagIcon code={code}/> {title}</>);
}}
>
<Dropdown.Toggle variant="secondary" id="dropdown-flags" className="text-left" style={{ width: 300 }}>
{toggleContents}
</Dropdown.Toggle>
<Dropdown.Menu>
{countries.map(({ code, title }) => (
<Dropdown.Item key={code} eventKey={code}><FlagIcon code={code}/> {title}</Dropdown.Item>
))}
</Dropdown.Menu>
</Dropdown>
</Form>
</div>
);
}
FlagIcon.js:
import React from 'react';
import FlagIconFactory from 'react-flag-icon-css';
// const FlagIcon = FlagIconFactory(React);
// If you are not using css modules, write the following:
const FlagIcon = FlagIconFactory(React, { useCssModules: false })
export default FlagIcon;
You'll get a dropdown button like this:
You can also check this working Stackblitz: https://stackblitz.com/edit/react-bootstrap-flags-dropdown-menu
Are you closing the tag
<Form.Control as="select">
[object Object] is displayed e.g when you are concatenating a string with an object, for example:
console.log(""+{})

How to test React dynamic style prop?

Am teaching myself React and am starting on testing. Using the recommended stuff from the docs... create-react-app, jest, testing-library/react. I have a component that renders a dynamic style, something like this
const ScalingDiv = (props) => (
<StyledDiv size={props.size || 42}>
<OtherEl>
{props.text}
</OtherEl>
</StyledDiv>
);
I would like to verify that my logic in there is working correctly (that 42 is used as a fallback size). I cannot find any examples or docs of this. I had hoped that something like this would work-
test('check fallback size', async () => {
const {container} = render(<ScalingDiv/>);
expect(container.firstChild).toHaveAttribute('size', 42);
});
But I haven't found any combination of matchers and queries that returns ANY attributes. Then I tried to just check the style directly using jest-dom, but toHaveStyle('this_isnt_valid_css: 199') passes- I couldn't stick anything in there to get it to fail. So... what is the right way to do this?
It's not attribute but prop. So we can refer to prop() and props() methods like
expect(container.firstChild.prop('size')).toEqual(42);
or
expect(container.firstChild.props()).toEqual({
size: 42
});

Css Selector in Framework7 vue

i try to build an Cordova/Phonegap application using vue.js and the Framework7.
I find out how to use functions like "onClick" using the "v-on:click="OnClick" attribute in an html element. Framework7 has jquery already implemented in the dom.
But there is one question. How can i access the dom directly, so that i can select whole css classes with the jquery selector. Like:
$('.likeButton'). ?
In the offical framework7 i found something like this to access the dom with its functions:
this.$$ or this.Dom7
This is what i have already written down in the home.vue file:
<script>
//import Fonts-awesome Icons
import FontAwesomeIcon from '#fortawesome/vue-fontawesome'
import {} from '#fortawesome/fontawesome-free-solid'
import F7Icon from "framework7-vue/src/components/icon";
import F7PageContent from "framework7-vue/src/components/page-content";
import * as Framework7 from "framework7";
export default {
name: 'FAExample',
components: {
F7PageContent,
F7Icon,
FontAwesomeIcon
},
methods: {
clickit: function () {
console.log("hi");
//this is what i have tested, looking if i have access to dom
let $$ = this.$$;
console.log($$);
},
//this is what i want to use
$('.likebutton').on('click',function () {
})
}
}
</script>
Did any of you have an idea how this works?
I hope you can help me. I'm new with vue.js in combination with the framework7.
Thank's for your help :)
We can use all the DOM functions just like
this.$$('.classname)
for example, if you want to hide something by jquery you can use as:
this.$$('.classname).hide()
To check all the DOM functions you can check the official documentation.
https://framework7.io/docs/dom7.html
But make sure that your DOM function should not in any Window function.
If you get the error to implemented it, just make the 'this' instance first.
Just like:
var self=this; // a global variable with this instance
use
self.$$('.classname).hide()
for any framework7 help, just ping me on skyp: sagardhiman5_1
Have you tried using Vue's $refs? You can set a reference to a specific DOM element and then access that in Vue.
A simple example:
<template>
<div class="some-item" ref="itemRef">Some item</div>
</template>
Then in the component:
var myItem = this.$refs.myItem;
// do what you want with that DOM item...
You can also access $refs from the parent. The example in the link below gives details on that.
More on $refs: https://v2.vuejs.org/v2/guide/components.html#Child-Component-Refs

AngularJS Material Dialog using component as template

I have an angular component which I want to use in an AngularJS Material dialog:
return $mdDialog.show({
template: '<publish-dialog user="$ctrl.user" target-collection="$ctrl.targetCollection"></publish-dialog>',
controller: function () {
this.user = user;
this.targetCollection = targetCollection;
},
controllerAs: '$ctrl',
targetEvent: event,
clickOutsideToClose: true
});
The problem is, that when defining the template like this, the generated html looks like this:
<md-dialog>
<publish-dialog>
<md-toolbar></md-toolbar>
<md-dialog-content></md-dialog-content>
<md-dialog-actions></md-dialog-actions>
</publish-dialog>
<md-dialog>
The component element is breaking the between md-dialog and md-toolbar, md-dialog-content and md-dialog-actions leads to a layout break and the md-toolbar and the md-dialog-actions are not fixed.
So my question is, is there a way to only render the component template contents without the component element (<publish-dialog></publish-dialog>)?
In your directive, try using replace: true.
From How to use `replace` of directive definition?

Vue 2.0 Laravel 5.3 Parent Child relationship with slot

I have a project where when i click on a anchor on parent item-sorting-list a property of child item-card will change so it sort something out based on that property. However the data does not seem to pass to the child. I am wondering if there is anything wrong when i built up the parent child relationship in the meanwhile?
template (item-sorting-list)
<a :name="subcat.name" href="" #click.prevent="getSelectedSubcat(subcat.name)">{{subcat.name}}</a>
methods (item-sorting-list)
methods: {
getSelectedSubcat(subcat){
var vm = this;
vm.selectedSubcat = subcat
}
}
When I click on the subcat.name, it does actually store subcat.name into selectedSubcat (verified from Vue devtool) in the item-sorting-list component. The problem is item-card does not store it even though i put selectedSubcat as props
HTML (does this work as parent child relationship here?)
<item-sorting-list><item-card></item-card></item-sorting-list>
UPDATED item-card
export default {
props:[
'selectedSubcat'
],
data(){
return {
products:[],
}
},
mounted() {
this.getAllProducts()
},
methods: {
getAllProducts(){
var vm = this;
vm.$http.get('/getProducts').then((response)=>{
vm.products = response.data.data.products;
});
}
}
}
from Vue devtool, item-card is included in the item-sorting-list, I would say that means they are parent child relationship? but then when i click something in item-sorting-list and change selectedSubcat, selectedSubcat in item-sorting-list does change but the selectedSubcat in item-card remains undefined. Sorry for my bad English.
UPDATE2
I notice that every example that I found online is that they set selectedSubcat in the new Vue with el="#app" in it instead of any other component (in my case item-sorting-list). Does that matter? I feel like the :selected-subcat="selectedSubcat in
<item-sorting-list>
<item-card :selected-subcat="selectedSubcat"></item-card>
</item-sorting-list>
cannot read the selectedSubcat that I defined in the component item-sorting-list but instead if i set selectedSubcat in the following
const app = new Vue({
el: '#app',
data:{
selectedSubcat:1
}
});
it does read selectedSubcat as 1. So what I would say is that item-card does not consider item-sorting-list as its parent. But why and how can I make it to become item-card's parent? [NOTE: but in the Vue devtool the tree does show that item-sorting-list does consist of item-card, item-card does show after clicking the arrow on the left of item-sorting-list]
In VueJs, you have parent child relation, when you don't register a vue component globally, but you make a component available only in the scope of another instance/component by registering it with the components instance option, like following:
var Child = {
template: '<div>A custom component!</div>'
}
new Vue({
// ...
components: {
// <my-component> will only be available in parent's template
'my-component': Child
}
})
In your case, I dont see selectedSubcat being passed as dynamic props to child component item-card. Dynamic props to data on the parent ensures whenever the data is updated in the parent, it will also flow down to the child:
You probably have to pass it to child like following:
<item-sorting-list>
<item-card :selected-subcat="selectedSubcat"></item-card>
</item-sorting-list>
You also have to add props in your item-list like this:
var itemList = {
props: ["selectedSubcat"]
template: '<div>Yout component!</div>'
}
notice I have converted it to kebab-case, because HTML being case-insensitive, camelCased prop names need to use their kebab-case (hyphen-delimited) equivalents(Documentation).

Resources