How to use Yandex.Metrika in Meteor+React app? - reactjs

I have a Meteor app, all UI components are built with React. I use FlowRouter for routing.
Now I want to add analytics with Yandex.Metrika service.
I found this package for React: https://github.com/narkq/react-yandex-metrika
But I how I have to use it? For what reason do I need <YM /> component from this example?
import {Initializer as YM} from 'react-yandex-metrika';
// Use the initializer to add the script to your page somewhere.
var MyComponent = React.createClass({
render: function() {
return (
<div>
// SNIP
<YM />
// SNIP
</div>
);
}
});
And where should I initialize the tracker object? I read this:
// This is supposed to be executed only in browser and only once.
// Because of that, the most sensible place for this code is right after you javascript bundle.
ym.init([987654321]);
But what is javascript bundle and where should I place my im.init(id) code?
Actually all what I need is to have funsctions to send data to Metrika, such as hit (pageview analog rom ga), reachGoal and so on.
thank you for your answers!

For what reason do I need component from this example?
You need it to load metrika's main code
How metrika works:
webmaster (you) inserts small piece of js code (loader) to all pages. this code append async script with main code (it's a bit bigger than loader) and create instance of metrika object ('counter') - new Ya.Metrika(...params). Instance will be available in global variable named yaCounterXXXXX, where XXXXX is your counter's id.
So, <YM /> component is loader from previous paragraph.
Actually all what I need is to have funsctions to send data to
Metrika, such as hit (pageview analog rom ga), reachGoal and so on.
There is doc about that at the bottom of readme. But I don't see filter by counter id for that methods. Maybe I make a pr to add this functionality. In any case you can use global variable yaCounterXXXXX like this yaCounterXXXXX.hit(url, params) or yaCounterXXXXX.reachGoal(goalId, params)
I hope I helped you.

Related

Copy button not working, need to link between 3 pages and can't link its id or value directly

Okay so my problem is that i have 3 seperate .html files 1 which loads in all the components for the overall page the second for the modal, and the third contains the actual input field that i need to get its value from.
The input field is nested inside the modal.
So i need to get the value of the input field, which ng-model is read from the database.
the pagination looks like main.html > importer.html > input.html
and input.html contains the value's i want, either its id or its value.
I don't expect you to solve my problem for me, i simply need someone to explain or create a snipet to resolve an id or its value in the same structure so i can reproduce it myself.
can't share source code as its licensed, i hope i have given a clear enough explanation for you to understand the concept.
i already tried every stackoverflow or tutorial thats out there, but these all have only 2 compenents/layers which makes it useless to what im doing.
The kind of question you ask is very specific and vague, which makes it difficult to answer and not very suited for StackOverflow. But I can give a general answer on how to share information across components in Angular: Angular wants you to use Services.
The general idea would be to:
Create a service
Inject the service in both components that need to send/receive the data
Use the service for access to Observables to send/receive data
1. Create the service
ng generate service my-service
2. Inject the service
At the top of both components' .ts files:
import { MyService } from 'src/app/my-service.ts';
In the constructor in both files:
construct(
private svc: MyService
) { }
3. Use Subjects to transmit events
The general idea of an observable/subject is that the receiver of data can subscribe to a stream of events and that the sender can place the next value onto the stream. You can use your service to expose such an observable/subject.
In the service:
import { Subject } from 'rxjs';
class MyService {
public events$ = new Subject();
}
In the receiver's ngOnInit:
ngOnInit() {
this.svc.events$.subscribe(
value => {
// What should happen with the new value?
}
);
}
Place this inside of the sending component whenever the value changes for your input field:
this.svc.events$.next(value);
PS: You could also simplify this depending on your use-case by using the service to expose a simple variable and depend on Angular's change detection.

How to make "global" variable available in Laravel helper and view?

I'm working on a Laravel app that I'm transitioning to React using a microfrontend(-like?) approach. I defined a helper function in Laravel that receives a component name and array of props and outputs the server-side rendered React HTML. I then call this function inside my views where needed.
Each page in my application defines a few variables that might affect the rendering both of these React components and also the Blade templates. So I define the variables in the view and send them to JavaScript land through a global window variable. But I also need these variables in the SSR helper.
Right now I have two ideas on how to do this:
Pass the variables as props in each call to my helper function. I want to avoid this as the variables will never change throughout the request lifecycle and all the #includes and #extends
Set the values using config helper before rendering the view. This seems kind of unidiomatic, as I think config should be used with more "static" values (that apply for the whole application and not particular pages), but I'm not very well versed in Laravel-world so this might actually be acceptable.
So right now I'm more inclined to 2, but I was wondering if there was a better option?
Some code:
my-template.blade.php
//these are the variables that I want to access in my helper
#extends('master.index', [
"_PAGE_CONFIG" => [
"page" => "blog",
"header" => ["search" => true]
]
]);
#section('content')
#include('some-template.that-also-has.ssr-components-in-it')
{!! ssr('blog/Blog', ["posts" => $posts]) !!}
#endsection
master/index.blade.php
<body>
#if($_PAGE_CONFIG["header"])
<header>{!! ssr('header/Header') !!}</header>
#endif
#yield('content')
<script>
//here I pass my variables to (client) JS land
window._PAGE_CONFIG = #json($_PAGE_CONFIG);
</script>
</body>
my-SSR-helper.php
function ssr($component, $props = []) {
/*
here I call a node server or script that handles the rendering for me,
but I want to pass it $_PAGE_CONFIG, which will be different in each page.
I could pass it in each ssr call in the template but this is what I want to avoid
as this function might be called several times down the #include/#extend chain
and $_PAGE_CONFIG never changes in any one page
(but might be different for different pages).
*/
}
If each page always gets the same values, then you should set an array somewhere into your config where the keys are the pages and the values are the props received. By the way, you would get:
function ssr($component, $page, $props = []) {
$pageProps = config('somewhere.'.$page);
}
I'm glad to see people using micro-frontends to use React to server-side rendering in a non-javascript framework like Laravel.
I recommend you take a look at this article Universal Rendering in Laravel using Vue.js and Ara Framework. Ara Framework supports also React, I think the server-side include approach is the best option to overcome the limitations of Blade.
This article can give you context about how this approach works.
https://itnext.io/strangling-a-monolith-to-micro-frontends-decoupling-presentation-layer-18a33ddf591b

Node Webkit / Angular / Change Model

Sorry for a not very specific question by someone new to node webkit, new to Angular, new to about everything in web development:
My app is based on a JSON file that I load at the init of my node webkit app and which is at the center of a bunch of calculations.
In the app, one can open a file dialog to create a new JSON file. Now, of course, I would like the app to recalculate everything based on the new JSON. It works when I press the "refresh" button of node webkit, but I couldn't get it running by using either
require('nw.gui').Window.open('index.html');
nor
require('nw.gui').Window.get().reload(3);.
I am also wondering if handling this on the node level is the good way to do it. Shouldn't it rather be done by Angular? But I couldn't really connect to the content of my controller from an "outside" javascript.
Grateful for any hint...
Having logic on the page loading is always tricky and as you mentioned - requires page reloading what is not very elegant and modern applications avoid this.
In your case, I suggest that if your JSON file is not very big - store it in variable and modify it as needed. The elegant way will be to create Angular service, which can act as a "model".
angular.service('JsonService', function() {
var json = {
// content
};
return {
getJson: function () {
return json;
},
setJson: function (newJson) {
json = newJson;
}
};
});
Then, whenever you need to update JSON invoke setJson(newJson) method and modify your controllers to use the service getJson() method.
You can also add the loading/saving to file functions to this service. The loading function can be invoked in your main controller connected to your dashboard page. Then before the first page will be visible, the JSON file will be already loaded and you preserve desired behavior.

Angular translate extend existing translations

I am trying to have external modules change my $translateProvider.translation on the main module. see this as a "tranlation plugin" for my app.
it seems like changing translations from the $translate service is not possible.
mymodule.service('MyService', function ($translateProvider) {
var lib = function () {
//EDITED FOR BREVITY
this._registerTranslations = function (ctrl) {
if (!ctrl.i18n) return;
for (var name in ctrl.i18n) {
/////////////////////////////
// THIS IS THE PLACE, OBVIOUSLY PROVIDER IS NOT AVAILABLE!!!!
$translateProvider.translations(name, ctrl.i18n[name]);
//////////////////////////////
}
};
//EDITED FOR BREVITY
};
return new lib();
});
anyone with a bright idea?
So, to answer your question: there's no way to extend existing translations during runtime with $translate service without using asynchronous loading. I wonder why you want to do that anyway, because adding translations in such a way means that they are already there (otherwise you would obviously use asynchronous loading).
Have a look at the Asynchronous loading page. You can create a factory that will load a translation from wherever you want.
I created an Angular constant to hold new translations. If I want to add a new translation, I add it to the constant. Then in my custom loader, I first check the constant to see if the translation exists (either a new one, or an updated one). If so, I load it from the constant. If not, I load it from a .json file (or wherever you load your initial translations from). Use $translate.refresh() to force translations to be reloaded and reevaluated.
Demo here
The demo is pretty simple. You would need to do a little more work if you wanted to just change a subset of the translations, but you get the general idea.
From the AngularJS docs (https://docs.angularjs.org/guide/providers):
You should use the Provider recipe only when you want to expose an API for application-wide configuration that must be made before the application starts. This is usually interesting only for reusable services whose behavior might need to vary slightly between applications.
Providers are to be used with the application's .config function. $translateProvider for configuration, $translate for other services and controllers.

CakePHP - Render a view that is actually plugin's view from Component

Morning guys,
So this is my first time developing a plugin for CakePHP. Here's what I am doing in startUp of the component.
//component
function startUp(&$controller){
//....
if($render){
$controller->render("return", "ajax");
}
}
By default render will look at app/views/<controllers>/return.ctp and app/views/layouts/ajax for this render call.
Is there anyway that I can give a directive to render from app/my_plugin/views/awesome_stuffs/return.ctp and app/my_plugin/views/layout/ajax.ctp instead?
I believe the third param of Controller::render($file, $layout, $file) could do the job, but is there any better Cake way of doing things?
Plus, is that considered a good practice to take over controller's rendering function like that?
One way is to call the PLUGIN controller/action URL in your AJAX call, instead of the main app controller/action URL.
ex:
instead of:
http://domain.com/controller/action
you call:
http://domain.com/my_plugin/controller/action
When you do it this way, the plugin views & layouts are called automagically. See:
http://book.cakephp.org/view/1118/Plugin-Tips
http://book.cakephp.org/view/1115/Plugin-Views
Otherwise, the only way I know of is manually setting paths as you mentioned or controller-wide via:
var $viewPath = 'path/to/plugin/views/';
var $layoutPath = 'path/to/plugin/layouts/';
You might want to try setting $this->view to the plugin dotted view file you want to render.
add to your source
$controller->plugin = "pluginname";

Resources