View not updating after changing value of component array - angular5

I need to update my view on changing array in my *.component.ts
I use
public getFolders() : void {
this.webService.getFolders({client_id : this.local.get('clientUser').client_id}).subscribe( this.processSkills.bind(this, this.local.get('clientUser')))
}
processSkills(res: any, myobj): void {
if(res.status){
myobj.folders = res.folders;
this.local.set('clientUser', myobj);
this.userObj = this.local.get('clientUser');
}
}
It updates my array i saw in console it update my session value which i saw after pressing F5 but it doesn't update my view
Initially i am assigning my array to variable from my session object.

import { BehaviorSubject } from 'rxjs';
private messageSource = new BehaviorSubject(this.local.get('clientUser'));
currentMessage = this.messageSource.asObservable();
I resolved it and found a solution to pass our array into session and make the code into our provider which works as observable to my array and then recieve
currentMessage to our receiver function to update on view.
this.webService.currentMessage.subscribe(message => {
this.userObj = message;
})
will receive updated value and will reflect on view.

Related

Vue.js 3 JavaScript Objects members losing ref reactivity

I'm updating a web app from using Knockout.js Templates to Vue 3 Components. This issue is not in the components but in the JS where I'm creating objects to be used in the components.
I'm running into strange behaviour around using refs where an object member is not always being set as a ref. I haven't been able to recreate this in an example but a simplified version of the structure is that we have an attribute that returns an object that contains the ref value.
function Attribute(val) {
var value = ref(val);
return {
value: value
}
}
We have a builder that is used to add labels and other items such permissions and classes to the UI.
function UIBuilder() {
var self = this;
var newElement = {};
function newText(value) {
newElement.inputType = 'TEXT';
newElement.value = value;
return self;
}
function addLabel(lbl) {
newElement.label = lbl;
return self;
}
function build() {
return newElement;
}
this.newText = newText;
this.addLabel = addLabel;
this.build = build;
}
Finally there is a function that returns an object that contains everything that the component needs.
function TextInput(initValue) {
var self = this;
self.label = initValue.label;
self.value = initValue.value;
var textInput = {
label: self.label,
value: self.value
};
return textInput;
}
Then I create an object to be passed to the component.
var attr = new Attribute(5225);
var textBox = new TextInput(new UIBuilder().newText(attr).addLabel('Description').build());
This structure works using Knockout and I'm trying to keep as much of the existing code as possible.
Most of the time this works but there are some occasions where the value is coming in as a string rather then a ref. I haven't been able to isolate why this is happening. While debugging most of the time the values for initValue.value and self.value look like this in the watch on VS Code.
On some occasions it changes to string values even though the objects were created using the same functions.
I checked the initValue object when taking the screenshot and it appeared to be a ref
As far as I can see the value should stay as a ref. I'm not unwrapping it in code. Why is this happening? What should I look for?

mobx challenge: getters and setters into an observable array

I'm trying to write getters and setters into an observable array and it isn't working. The code below gives me the following error: Error: [MobX] No annotations were passed to makeObservable, but no decorator members have been found either
I've tried different combinations of decorators, but nothing seems to work. The behavior I want is whenever AppModel.text is updated, any UI rending the getter for text should update. Also whenever gonext() is called on the object, then any UI rending from AppModel.text should update and render data from the new 0 item on the array.
class DataThing
{
#observable text?: string = "foo";
}
class AppModel
{
get text() { return this.items[0].text}
set text(value: string | undefined) { this.items[0].text = value;}
items: DataThing[] = observable( new Array<DataThing>());
constructor() {
makeObservable(this);
this.items.push(new DataThing());
}
gonext() { this.items.unshift(new DataThing()); }
}
EDIT:
I ended up doing the following, but would still like to understand how to index into an array in an observable way.
class DataThing
{
#observable text?: string = "zorp";
constructor(){makeObservable(this);}
}
class AppModel
{
#observable _current?:DataThing;
get current() {return this._current;}
items: DataThing[] = observable( new Array<DataThing>());
constructor() {
makeObservable(this);
this.gonext();
}
gonext() {
this.items.unshift(new DataThing());
this._current = this.items[0];
}
}

Mobx Initial Data from Server

How can I set the value of mobx store from server side as initial value (from fetch/http)?
import { computed, observable } from 'mobx';
import { Instrument } from '../models/core/instrument';
class ObservableInstrumentStore {
//should set init value from server instead of setting to empty array
#observable instruments: Instrument[] = [];
#computed get getInstruments(): Instrument[] {
return this.instruments;
}
addInstruments(instruments: Instrument[]): void {
this.instruments = instruments;
}
}
export const observableInstrumentStore = new ObservableInstrumentStore();
How would you do it you weren't using mobx and observables?
There are some options.
Wait for the array to have length bigger than zero in order to do something with the data.
Have a flag that signals that loading of data is finished and then try to do something with the data.

Aurelia-Validation - Clarity on object validation w/addObject()

I'm attempting to manually validate an object which is updated via a customEvent.
//home.html
<type-ahead change.delegate="updateValue($event.detail, true/false)"></type-ahead>
I have two of the above elements, which I want to assign to the properties of origin and destination based on a boolean value.
I also want to validate both of these properties against the same custom rule, which I've defined in setupValidation on my viewmodel below.
Both of these are objects, that need some complex validation (I've simplified it for demonstration purposes), so I've used .ensureObject() and manually add both of these objects to the validation controller.
I would expect that I would only have to add the objects once (during my initial setupValidation(), but I've found that I have to remove, and then re-add the object to the validation controller whenever it changes.
If you look at updateValue(...), you'll see that I'm expecting this.destination to validate to the updated object, but I'm seeing my results still be null on validation. However, this.origin does update and the validation succeeds (as I'm manually updating the controller).
I would expect not to have to manually update the controller. Is this expected?
//home.ts
#autoinject
export class Home {
origin = null;
destination = null;
private controller: ValidationController;
public canSubmit: boolean = false;
public error: string;
private rules;
constructor(controllerFactory: ValidationControllerFactory) {
this.controller = controllerFactory.createForCurrentScope();
this.controller.validateTrigger = validateTrigger.manual;
}
bind() {
this.setupValidation();
}
private validate() {
this.controller.validate()
.then(results => {
this.canSubmit = results.valid;
});
}
private setupValidation() {
ValidationRules.customRule(
'rule1',
(value) => {
if(value.property && value.property.length === 3)
return true;
else
return false;
},
`\${$displayName} must be 3 characters long`
);
this.rules = ValidationRules
.ensureObject()
.required()
.satisfiesRule('rule1')
.rules;
this.controller.addObject(this.origin, this.rules);
this.controller.addObject(this.destination, this.rules);
}
updateValue(newValue, isOrigin) {
if(isOrigin) {
this.controller.removeObject(this.origin);
this.origin = newValue;
this.controller.addObject(this.origin, this.rules);
}
else
this.destination = newValue;
this.validate();
}
}
Thank you, let me know if there are any additional details needed.

singleton object in react native

I'm new in react native.I want store multiple small small strings to common singleton object class and want to access it from singleton object for all component. Can anyone help me singleton object implementation for react native.
Ex
Component 1 -- Login button -- >> success --> need to store userID into singleton object.
Component 2 --> get stored userID from singleton object. How can i implement it.
Here is a simple way of doing it...
export default class CommonDataManager {
static myInstance = null;
_userID = "";
/**
* #returns {CommonDataManager}
*/
static getInstance() {
if (CommonDataManager.myInstance == null) {
CommonDataManager.myInstance = new CommonDataManager();
}
return this.myInstance;
}
getUserID() {
return this._userID;
}
setUserID(id) {
this._userID = id;
}
}
And here is how to use it...
import CommonDataManager from './CommonDataManager';
// When storing data.
let commonData = CommonDataManager.getInstance();
commonData.setUserID("User1");
// When retrieving stored data.
let commonData = CommonDataManager.getInstance();
let userId = commonData.getUserID();
console.log(userId);
Hope this works out for you :)
I suggest making a static class that stores data using AsyncStorage.
You mentioned in a comment that you are already using AsyncStorage, but don't like spreading this functionality throughout your app. (i.e. try-catches all over the place, each component needing to check if a key is available, etc.) If this functionality were in a single class, it would clean up your code a lot.
Another bonus to this approach is that you could swap out the implementation pretty easily, for example, you could choose to use an in-memory object or AsyncStorage or whatever and you would only have to change this one file
NOTE: AsyncStorage is not a safe way to store sensitive information. See this question for more info on the security of AsyncStorage and alternatives.
That said, this is how I imagine a global data holder class might look:
export default class dataManager {
static storeKeyValue(key, value) {
// your choice of implementation:
// check if key is used
// wrap in try-catch
// etc.
}
static getValueForKey(key) {
// get the value out for the given key
}
// etc...
}
Then to use this class anywhere in your app, just import wherever it's needed like so:
import dataManager from 'path/to/dataManager.js';
// store value
dataManager.storeKeyValue('myKey', 'myValue');
// get value
const storedValue = dataManager.getValueForKey('myKey');
EDIT: Using Flux, Redux, or a similar technology is probably the preferred/suggested way to do this in most cases, but if you feel the Singleton pattern works best for your app then this is a good way to go. See You Might Not Need Redux
There is a workaround for this, react native packager require all the modules in the compilation phase for a generating a bundle , and after first require it generates an internal id for the module, which is from then on referenced in the whole run-time memory , so if we export an instance of a class from the file, that object will be referenced every-time whenever that file is imported .
TLDR;
Solution I :
class abc {
}
module.exports = new abc()
Solution II : I assume you want to get your strings which are static and wont change , so you can declare them as static and access them directly with class name
FYI :this works with webpack also.
I might be too late for this, but I might as well share my own implementation based on Yeshan Jay's answer.
export default class Data {
static instance = null;
_state = {};
static get inst() {
if (Data.instance == null) {
Data.instance = new Data();
}
return this.instance;
}
static get state() {
return Data.inst._state;
}
static set state(state) {
Data.inst._state = state;
}
static setState(state) {
Data.inst._state = {...Data.inst._state, ...state}
}
}
And here's how you use it. It's pretty much mimicking React Component's state behavior, so you should feel at home with little to no adjustment, without the need to frequently modify the Singleton to add new properties now and then.
import Data from './Data'
// change the whole singleton data
Data.state = { userId: "11231244", accessToken: "fa7sd87a8sdf7as" }
// change only a property
Data.setState ({ userId: "1231234" })
// get a single property directly
console.log("User Id: ", Data.state.userId)
// get a single property or more via object deconstruction
const { userId, property } = Data.state
console.log("User Id: ", userId)
TS Class Example:
export class SingletonClass
{
private static _instance: SingletonClass;
public anyMetod(_value:any):any
{
return _value;
}
public static getInstance(): SingletonClass
{
if (SingletonClass._instance == null)
{
SingletonClass._instance = new SingletonClass();
}
return this._instance;
}
constructor()
{
if(SingletonClass._instance)
{
throw new Error("Error: Instantiation failed: Use SingletonClass.getInstance() instead of new.");
}
}
}
Use:
SingletonClass.getInstance().anyMetod(1);