lega911 / angular-light

Alight is a library for building interactive MVVM web interfaces/applications. (project is deprecated)
MIT License
274 stars 43 forks source link

Scope nesting #232

Closed rumkin closed 7 years ago

rumkin commented 7 years ago

How can I provide proper nested scopes destroy?

I have stack of modals which is presented as sibling elements:

<my-modal id=1></my-modal>
<my-modal id=2></my-modal>
<my-modal id=3></my-modal>

Modal 3 initiated from modal 2 and so. Each modal has it's own scope (modal1 has scope1 and so). This scopes are nested. When I try to destroy scope1 then scope2 should be destroyed too.

Currently I'm doing it this way:

let parent = alight.Scope({changeDetector: null, $parent: scope});
parent.$rootChangeDetector = env.changeDetector.new(parent);

let child = alight.Scope({changeDetector: null, $parent: parent});
child.$rootChangeDetector = env.changeDetector.new(child);

parent.$watch('$destroy', () => {
    console.log('destroy parent');
    child.$destroy();
});

child.$watch('$destroy', () => {
    console.log('destroy child');
});

Am I missing something? What the proper way to do it? Maybe parent scope should call $destroy at child scopes automatically?

lega911 commented 7 years ago

Something like this: https://jsfiddle.net/lega911/rj2qj2zg/

using change detector: 0.12 https://jsfiddle.net/lega911/4e1nmexy/ similar in 0.14 https://jsfiddle.net/lega911/mqm20k2b/

rumkin commented 7 years ago

It looks strange that sometimes I get error 'No change detector' event if I create scope with $new() and I should to call scope.$changeDetector = scope.$rootChangeDetector; anytime to prevent it. Why could scope not to have CD?

lega911 commented 7 years ago

some explanation is here http://angular-light.readthedocs.io/en/latest/change_detector.html#how-does-it-work

briefly:

var scope = {};
var cd1 = new ChangeDetector(scope); // for one directive, e.g. al-if
var cd2 = new ChangeDetector(scope); // for another directive

cd1 has cd1.watch and cd2 has cd2.watch (it's impossible to use one changeDetector for everything) so which "watch" should be called if you call scope.$watch? there are cases when impossible to know which changeDetector.watch should be called, in this case you have 'No change detector'

it's why I voided scope in 0.14, it is like just rendering template:

var data = {title: 'hello'};  // object with data
var cd = alight('#app', data);  // render data to DOM

data.title = 'new value';  // change data
cd.scan();  // re-render data to DOM
lega911 commented 7 years ago
<div al-if="first">  {{parent}}
  <div al-if="second"> {{child}}
  </div>
</div>

in this case: 1) first al-if creates changeDetector and {{parent}} is placed to it 2) second al-if creates child changeDetector and {{child}} is placed to it

so when you switch second to false, then second al-if will destroy child changeDetector and {{child}} will be removed. if you would put everything in root changedetector, then {{child}} would not be removed.