Coder Social home page Coder Social logo

Comments (17)

JoaoSaleiro avatar JoaoSaleiro commented on September 23, 2024

Actually, this seems to be a characteristic of Angular Directives when transcluding automatically (transclude: true). So I would advise warning about this on the docs, and proposing a recommended approach.

from onsenui.

kruyvanna avatar kruyvanna commented on September 23, 2024

+1

from onsenui.

JoaoSaleiro avatar JoaoSaleiro commented on September 23, 2024

By the way, my second option doesn't work as expected. If you use

<ons-page > 
<div ng-controller="MyCtrl">
</div>
</ons-page>

when the inner div is transcluded, the scope of MyCtrl is not immediately applied.

from onsenui.

JoaoSaleiro avatar JoaoSaleiro commented on September 23, 2024

This also applies to other components, being the ons-navigator the most problematic one.

Imagine the following case with a ons-navigator:

<ons-navigator
            left-button-icon="fa fa-bars"
            title="{{defaultPage.title}}"
            on-left-button-click="decideTheAction()"
            page="{{defaultPage.url}}">


    </ons-navigator>

decideTheAction() is a method in a Controller. For decideTheAction to exist, since it can't be set in ons-navigator directly, it needs to be in a div before the ons-navigator. Unfortunately, in that case the controller won't be able to access "$scope.ons.navigator".

So, the current approach makes it a bit harder to implement more complex navigations.

A workaround (for this specific case) could be something like:

        on-left-button-click="ons.navigator.pushPage(getThePageURL())"

from onsenui.

JoaoSaleiro avatar JoaoSaleiro commented on September 23, 2024

This is actually becoming quite problematic, and making me reconsider onsenUI.

Imagine, for example, the following use case:

<body ng-controller="AppCtrl">
    <ons-screen page="connected.html"></ons-screen>
</body>

AppCtrl needs to perform some logic to decide what to show to the user at start. The problem is that AppCtrl doesn't have access to ons.screen , so it cannot call, for example, presentPage.

This could be solved if one could do:

<body ng-controller="AppCtrl">
    <ons-screen page="connected.html" ng-controller="MyScreenCtrl"></ons-screen>
</body>

Then, both controllers could talk, and MyScreenCtrl would have access to ons.screen .

So far, I haven't yet found an easy and clean solution for this.
The dirty hack, for now, consists in putting the following code in the link() function of onsScreen directive:

scope.$parent.ons = scope.ons; 

from onsenui.

kruyvanna avatar kruyvanna commented on September 23, 2024

in my case i used

index.html

<body ng-controller="AppCtrl">
    <ons-screen page="initial_page.html"></ons-screen>
</body>

initial_page.html

<div ng-show="user.loggedIn == true">
       <ng-include src="'connected.html'"></ng-include>
</div>

<div ng-show="user.loggedIn == false">
       <ng-include src="'not_connected.html'"></ng-include>
</div>

controller

myApp.controller('AppCtrl', function($scope) {
    $scope.user = {
        loggedIn: false;
    }

    $scope.login = function(){
        $scope.user.loggedIn = true;
    };

    $scope.logout = function(){
        $scope.user.loggedIn = false;
    }
});

i hope this help your use case.

from onsenui.

JoaoSaleiro avatar JoaoSaleiro commented on September 23, 2024

That was my first try, but it didn't (and doesn't work), because initial_page.html doesn't have access to the AppCtrl scope! See below:

index.html

<body ng-controller="AppCtrl">
    <ons-screen page="start.html"></ons-screen>
</body>

AppCtrl.html

myApp.controller('AppCtrl', function ($scope) {
  $scope.myVar = "Test";
});

start.html

<div style="color: #ffffff">    
    {{myVar}}
</div>

start.html should show "Test". But it's empty.

If I debug it with the console, doing a:

angular.element($0).scope();

while having the div in start.html selected, the scope() that appears doesn't have myVar.
Using AngularJS extension for chrome, I can see that I have three scopes. start.html has it's own scope, that is created by ons-screen. That scope is not inheriting from AppCtrl.

Also, the generated HTML shows a class="ng-isolate-scope" in < ons-screen >.

I was using AngularJS 1.2.12 and switched to the 1.2.10 bundled with onsen just to check. The issue maintains.

I don't see anything wrong with my code: it's simply that elements generated after a directive get their own scope, without inheritance to the previous scope.

from onsenui.

JoaoSaleiro avatar JoaoSaleiro commented on September 23, 2024

It's weird that your code works, since the ons-screen directive has it's own scope, and has transclude false. When this happens, the supposed behavior is:

"scope: { ... } - the directive creates a new isolate/isolated scope. It does not prototypically inherit the parent scope. "

See more at http://stackoverflow.com/questions/17900201/how-to-access-parent-scope-from-within-a-custom-directive-with-own-scope-in-an

And here's the contents of the directive:

    directives.directive('onsScreen', function(ONSEN_CONSTANTS, $http, $compile) {
        return {
            restrict: 'E',
            replace: false,
            transclude: false,
            scope: {
                page: '@'
            },

This leads into my current issue with Onsen that is making it hard to architect a simple app with a somewhat complex navigation.

from onsenui.

kruyvanna avatar kruyvanna commented on September 23, 2024

I am thinking of compiling the content of screen page against screen parent's scope. This way, screen's isolated scope will not get in the way.

It would be nice if you can test your code against this "screen_scope" branch.
https://github.com/OnsenUI/OnsenUI/tree/screen_scope

from onsenui.

JoaoSaleiro avatar JoaoSaleiro commented on September 23, 2024

I confirm the branch works fine for this test case.

In start.html I get "Test", so it's binding correctly. Nicely done :)
Will this be merged?

from onsenui.

kruyvanna avatar kruyvanna commented on September 23, 2024

yes!

from onsenui.

JoaoSaleiro avatar JoaoSaleiro commented on September 23, 2024

Great! 👍

I'm doing some tests with the changes you did in the screen_scope branch.
"ons" is now available in the $parent scope, but there's a little catch.

If you call ons.screen.presentPage on the parent scope immediately, an error will happen. This is because compilation and linking is not immediate. To fix it, calls to "presentPage" need to be wrapped in a $timeout 0, to ensure that the call is run on the next cycle.

Not working:

b.controller('AppCtrl', function ($scope) {
  $scope.ons.screen.presentPage('start_welcome.html');
}

Working:

b.controller('AppCtrl', function ($scope, $timeout) {
  $timeout(function () {
    $scope.ons.screen.presentPage('start_welcome.html');
  }, 0);
}

On a side note, I want to say thank you not only for your great work, but also for being on top of these issues. :)

from onsenui.

JoaoSaleiro avatar JoaoSaleiro commented on September 23, 2024

onsNavigator still has this issue, since it's scope is not compiled with it's parent scope:

onsNavigator (not working):

        link: function(scope, element, attrs) {
                            [...]
            scope.ons = scope.ons || {};
            scope.ons.navigator = scope.ons.navigator || {};

onsScreen (working):

        link: function(scope, element, attrs) {
            var screenItems = [];
            scope.$parent.ons = scope.$parent.ons || {};
            scope.$parent.ons.screen = scope.$parent.ons.screen || {};

from onsenui.

kruyvanna avatar kruyvanna commented on September 23, 2024

sorry wrong reference.

from onsenui.

kruyvanna avatar kruyvanna commented on September 23, 2024

i compiled with $parent scope on this branch feature/navigation_binding

from onsenui.

kruyvanna avatar kruyvanna commented on September 23, 2024

Now screen, navigator, sliding_menu, and split_view scope are compiled with parent's scope.
Also you can now set ng-controller in page.

<ons-page ng-controller="MyController">

it's merged into dev branch.

from onsenui.

rikur avatar rikur commented on September 23, 2024

+1

It's on dev branch, but still not on master and merging the feature/navigation_binding creates a bunch of conflicts.

from onsenui.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.