React DevTools: How to append component filters programmatically? - react-devtools

I use React DevTools Chrome Extension. I want to append component filters from a react app code. Is there a way to do this?
In common I want to share default application DevTools settings across the app developers.

I figured out. Here's an example:
if (__REACT_DEVTOOLS_GLOBAL_HOOK__) {
const handleReactDevtools = (agent) => {
__REACT_DEVTOOLS_COMPONENT_FILTERS__.push({
type: 2,
isEnabled: true,
isValid: true,
value: "HideMe"
});
agent.updateComponentFilters(__REACT_DEVTOOLS_COMPONENT_FILTERS__);
};
if (__REACT_DEVTOOLS_GLOBAL_HOOK__.reactDevtoolsAgent) {
handleReactDevtools(__REACT_DEVTOOLS_GLOBAL_HOOK__.reactDevtoolsAgent);
} else {
__REACT_DEVTOOLS_GLOBAL_HOOK__.on("react-devtools", handleReactDevtools);
}
}

Related

mmenu wordpress plugin - bind open / close events

I am using the licenced wordpress plugin version 3.1.0.
I have the menu working, but I cannot access the mmenu API to trigger the button open / close effect I would like to use. Previously I have used the mmenu core version [not WP plugin] and triggered the class changes using this:
var $menu = $("#menu").mmenu({...})
var API = $menu.data("mmenu");
API.bind("open:finish", function () {
$("#menu-btn").addClass("is-active");
});
API.bind("close:finish", function () {
$("#menu-btn").removeClass("is-active");
});
Modifying the var API to use the plugin generated id fails with undefined, probably because the menu creation is managed in a different script.
var API = $('#mm-1').data("mmenu"); //'mm-1' - the plugin generated mmenu id
I have also tried to use jQuery direct on #menu-btn but it is not triggered unless I remove the #menu-btn from the mmenu settings. For example [not copied, just a rough example so please ignore syntax errors]:
$("#menu-btn").click(function(){console.log('click')});
all I need is to add / remove an 'is-active' class to the open menu link [id=menu-btn].
The mmenu adds a body class when opened, so added a mutation observer to check if the has the .mm-wrapper--opened class or not. If it does, add the 'is-active' class to the menu icon (which uses the .hamburger class) and if not, remove it.
if ($('body').hasClass('mm-wrapper--opened')){
$('.hamburger').addClass("is-active");
}
const targetNode = document.body;
const config = { childList : true, attributes: true };
const callback = function(mutationsList, observer) {
for(let mutation of mutationsList) {
if (mutation.type === 'attributes') {
if ($('body').hasClass('mm-wrapper--opened')){
setTimeout(() => { $('.hamburger').addClass("is-active"); }, 500);
}
else {
$('.hamburger').removeClass("is-active");
}
}
}
};
const observer = new MutationObserver(callback);
observer.observe(targetNode, config);

How to connect google analytics to Nuxt3 app?

I have a problem. I try to connect my Nuxt3 app with Google Analytics.
right now I do it by adding to nuxt.config.ts following code
export default defineNuxtConfig({
buildModules: [
'#nuxtjs/google-analytics'
],
googleAnalytics: {
id: process.env.GOOGLE_ANALYTICS_ID
},
})
but unfortunately I get following error when I try to build my app
ERROR Error compiling template: { 17:53:04
ssr: false,
src: 'C:\\Users\\szczu\\Elektryk\\node_modules\\#nuxtjs\\google-analytics\\lib\\plugin.js',
fileName: 'google-analytics.js',
options: {
dev: true,
debug: {
sendHitTask: true
},
id: undefined
},
filename: 'google-analytics.js',
dst: 'C:/Users/szczu/Elektryk/.nuxt/google-analytics.js'
}
ERROR serialize is not defined 17:53:04
at eval (eval at <anonymous> (node_modules\lodash.template\index.js:1550:12), <anonymous>:7:1)
at compileTemplate (/C:/Users/szczu/Elektryk/node_modules/#nuxt/kit/dist/index.mjs:493:45)
at async /C:/Users/szczu/Elektryk/node_modules/nuxt3/dist/chunks/index.mjs:1296:22
at async Promise.all (index 11)
at async generateApp (/C:/Users/szczu/Elektryk/node_modules/nuxt3/dist/chunks/index.mjs:1295:3)
at async _applyPromised (/C:/Users/szczu/Elektryk/node_modules/perfect-debounce/dist/index.mjs:54:10)
Does anyone have an idea how to fix it?
Try the vue-vtag-next package as a plugin
yarn add --dev vue-gtag-next
Create a plugin file plugins/vue-gtag.client.js
import VueGtag from 'vue-gtag-next'
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.use(VueGtag, {
property: {
id: 'GA_MEASUREMENT_ID'
}
})
})
Late reply, but i would like to add for any future viewers.
The above solution only worked for me when the $router was passed. Please find below sample code.
Please also note:
The package being used, 'vue-gtag' instead of 'vue-gtag-next'.
You have to pass config object instead of property for the 'vue-gtag' package
import VueGtag from 'vue-gtag'
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.use(VueGtag, {
config: {
id: 'GA_MEASUREMENT_ID',
},
}, nuxtApp.$router)
})
found this solution https://github.com/nuxt/framework/discussions/5702
.. And also you may use nuxt.config to provide app.head.script with children attribute on the app level:
import { defineNuxtConfig } from "nuxt";
export default defineNuxtConfig({
app: {
head: {
script: [{ children: 'console.log("test3");' }],
},
},
});
import VueGtag from 'vue-gtag-next'
export default defineNuxtPlugin(async (nuxtApp) => {
const { data: { value: {google_id, google_sv, yandex_id, privacy_policy} } } = await useMyApi("/api/main/site-metriks/");
nuxtApp.vueApp.use(VueGtag, {
property: {
id: google_id
}
})
})
For Nuxt 3:
Install vue-gtm: npm i #gtm-support/vue-gtm
Create file in /plugins/vue-gtm.client.ts
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.use(createGtm({
id: 'GTM-ID',
defer: false, // Script can be set to `defer` to speed up page load at the cost of less accurate results (in case visitor leaves before script is loaded, which is unlikely but possible). Defaults to false, so the script is loaded `async` by default
compatibility: false, // Will add `async` and `defer` to the script tag to not block requests for old browsers that do not support `async`
nonce: '2726c7f26c', // Will add `nonce` to the script tag
enabled: true, // defaults to true. Plugin can be disabled by setting this to false for Ex: enabled: !!GDPR_Cookie (optional)
debug: true, // Whether or not display console logs debugs (optional)
loadScript: true, // Whether or not to load the GTM Script (Helpful if you are including GTM manually, but need the dataLayer functionality in your components) (optional)
vueRouter: useRouter(), // Pass the router instance to automatically sync with router (optional)
//ignoredViews: ['homepage'], // Don't trigger events for specified router names (optional)
trackOnNextTick: false, // Whether or not call trackView in Vue.nextTick
}))
})
Nuxt would automatically pick up this plugin and you're done.

Detect change to modelValue in Vue 3

Is there a way to detect change to modelValue in a custom component? I want to push the change to a wysiwyg editor.
I tried watching modelValue but emitting update for modelValue triggered that watch, which created circular data flow.
Code:
export default {
props: ['modelValue'],
watch: {
modelValue (val) {
this.editor.editor.loadHTML(val)
}
},
mounted () {
this.editor.editor.loadHTML(val)
this.editor.addEventListener('trix-change',
(event) => this.$emit('update:modelValue', event.target.value))
}
}
<TextEditor v-model="someHtml"></TextEditor>
In VueJS v3, the event name for custom v-model handling changed to 'update:modelValue'.
You can listen to these events like this: v-on:update:modelValue="handler"
For a more complete example, lets assume you have a Toggle component with these properties/methods:
...
props: {
modelValue: Boolean,
},
data() {
return {
toggleState: false,
};
},
methods: {
toggle() {
this.toggleState = !this.toggleState;
this.$emit('update:modelValue', this.toggleState);
}
}
...
You can use that Toggle component:
<Toggle v-model="someProperty" v-on:update:modelValue="myMethodForTheEvent"/>
As a side note, you could also v-model on a computed property with a setter; allowing you to internalise your state changes without using the update:modelValue event. In this example, it assumes you v-model="customProperty" on your custom Toggle component.
computed: {
customProperty: {
get() {
return this.internalProperty;
},
set(v) {
this.internalProperty = v;
console.log("This runs when the custom component 'updates' the v-model value.");
},
}
},
I had the same problem and solved it using a slight tweak to the way you call the watch function:
setup(props) {
watch(() => props.modelValue, (newValue) => {
// do something
})
}
Hence, the important thing is to add () => props.modelValue instead of just putting props.modelValue as the first argument of the watch function.
try that:
watch: {
...
modelValue: function(val) {
console.log('!!! model value changed ', val);
},
...

Integrate MPGS session.js in Aurelia SPA

I am trying to integrate the MasterCard Payment Gateway services to a SPA using Aurelia.
I am trying to use the hosted checkout mechanism to integrate MPGS.
I am writing code in the attached event of the Aurelia viewmodel to load the session.js library and on load of the library adding another script element to initialize the session.
The attached method is listed below.
this.mpgsSessionScript = `if (self === top) { var antiClickjack = document.getElementById("antiClickjack"); antiClickjack.parentNode.removeChild(antiClickjack); } else { top.location = self.location; } PaymentSession.configure({ fields: { card: { number: "#card-number", securityCode: "#card-cvv", expiryMonth: "#card-expiry-month", expiryYear: "#card-expiry-year" } }, frameEmbeddingMitigation: ["javascript"], callbacks: { initialized: function(response) { console.log(response); }, formSessionUpdate: function(response) { } } }); function pay() { PaymentSession.updateSessionFromForm('card'); }`;
this.styleElement = document.createElement('style');
this.styleElement.setAttribute('id', "antiClickjack");
this.styleElement.innerText = "body{display:none !important;}";
document.head.appendChild(this.styleElement);
this.scriptElement = document.createElement('script');
this.scriptElement.src = this.sessionJs;
this.scriptElement.onload = () => {
const innerScriptElement = document.createElement('script');
innerScriptElement.innerText = this.mpgsSessionScript;
document.body.appendChild(innerScriptElement);
};
document.body.appendChild(this.scriptElement);
I can successfully run the code the and the script elements are added to DOM and also, the antiClickjack style gets removed, which indicates that the script element gets added.
But the issue is, the card number and the cvv elements are not getting enabled for input. If successfully initialized, the card number and the cvv elements should get enabled.
I do not see any errors in the console. Any help would be appreciated.

onChange will not fire with delayed state changes and later added components ReactMeteor

A very basic and standard component which should call the change handler when the input changes.
It works in my pen: http://codepen.io/sdbondi/pen/MaGovq
It doesn't in my meteor app - in fact any handler (onClick, etc) doesn't work if rendered after the initial page load - { (this.state.cond) ? <Element onChange={..}/> : ''} will also render but not fire the change.
Interestingly changes fire if I set the entries in the initial state, but with setTimeout they render but no onChange.
I've stepped through react to try and understand how events are bound (I actually got to addEventListener eventually) but it'll take a while to understand what is happening enough to debug.
export default React.createClass({
displayName: 'VotePage',
getInitialState() {
return {
entries: []
};
},
handleChange(e) {
console.log(e);
},
componentDidMount() {
// this will eventually be replaced by meteor data (ReactMeteor.createClass etc)
window.setTimeout(() => {
this.setState({'entries': [{_id: '123', name: 'guyuy'}, {_id:234, name: 'sadfsd'}]});
}, 1000);
},
render() {
var voteEntries;
if (this.state.entries && this.state.entries.length) {
voteEntries = this.state.entries.map((entry) =>
<input key={entry._id} name="entry" type="text" onChange={this.handleChange} defaultValue={entry.name} />
);
} else {
voteEntries = 'loading...';
}
return (
<div>
<h2>Vote</h2>
<div className="island_-small">
{voteEntries}
</div>
</div>
);
}
});
React: v0.13.0 (tried 0.13.3 too)
------------> versions excerpt
react#0.1.13
react-meteor-data#0.1.9
react-runtime#0.13.3_7
react-runtime-dev#0.13.3_7
react-runtime-prod#0.13.3_6
reactive-dict#1.1.3
reactive-var#1.0.6
reactjs:react#0.2.4
kadira:flow-router#2.7.0
kadira:react-layout#1.4.1
----------> packages full file
meteor-base # Packages every Meteor app needs to have
mobile-experience # Packages for a great mobile UX
mongo # The database Meteor supports right now
blaze-html-templates # Compile .html files into Meteor Blaze views
session # Client-side reactive dictionary for your app
tracker # Meteor's client-side reactive programming library
standard-minifiers # JS/CSS minifiers run for production mode
es5-shim # ECMAScript 5 compatibility for older browsers.
dburles:collection-helpers
aldeed:collection2
accounts-base
accounts-password
alanning:roles
# twbs:bootstrap
# fortawesome:fontawesome
wylio:mandrill
# kadira:blaze-layout
# sach:flow-db-admin
check
stevezhu:lodash
accounts-facebook
service-configuration
kadira:flow-router
universe:modules-npm
ecmascript
fixate:app-deps
universe:modules
yasaricli:slugify
maxharris9:classnames
reactjs:react
kadira:react-layout
jquery
react-meteor-data
meteorhacks:subs-manager
Was something in reactjs:react. See https://github.com/reactjs/react-meteor/issues/105
I made this mixin based on froatsnooks response on github:
export const MeteorReactSubscriber = {
componentWillMount() {
this._subsMap = {};
this.subscriptions();
this._startMeteorTracker();
},
_startMeteorTracker() {
this._subsHandle = Tracker.autorun(() => {
this.subscriptionReady && this.subscriptionReady();
if (this.meteorSubsReady()) {
this.meteorDataReady && this.meteorDataReady();
}
});
},
meteorSubsReady() {
return _.all(this._subsMap, (s, _) => s.ready());
},
meteorSubscribe(name, selector=undefined) {
this._subsMap[name] = Meteor.subscribe(name, selector);
},
componentWillUnmount() {
this._subsHandle.stop();
this._subsMap = null;
}
};
Usage
var SweetComponent = React.createClass({
mixins: [MeteorReactSubscriber],
subscriptions() {
this.meteorSubscribe('entries');
},
meteorDataReady() {
var currentEntry = Entry.findOne(this.props.entryId);
this.setState({entry});
},
render() { ... }
});

Resources